gre: Tunnel encap/decap flags
[vpp.git] / src / vnet / ip / ip4_packet.h
index 1ff9fbd..3872ccd 100644 (file)
@@ -64,10 +64,11 @@ typedef struct
 } ip4_address_fib_t;
 
 always_inline void
-ip4_addr_fib_init (ip4_address_fib_t * addr_fib, ip4_address_t * address,
-                  u32 fib_index)
+ip4_addr_fib_init (ip4_address_fib_t * addr_fib,
+                  const ip4_address_t * address, u32 fib_index)
 {
-  clib_memcpy (&addr_fib->ip4_addr, address, sizeof (addr_fib->ip4_addr));
+  clib_memcpy_fast (&addr_fib->ip4_addr, address,
+                   sizeof (addr_fib->ip4_addr));
   addr_fib->fib_index = fib_index;
 }
 
@@ -77,9 +78,14 @@ typedef struct
   ip4_address_t src, dst;
 } ip4_address_pair_t;
 
+typedef struct
+{
+  ip4_address_t addr, mask;
+} ip4_address_and_mask_t;
+
 /* If address is a valid netmask, return length of mask. */
 always_inline uword
-ip4_address_netmask_length (ip4_address_t * a)
+ip4_address_netmask_length (const ip4_address_t * a)
 {
   uword result = 0;
   uword i;
@@ -132,7 +138,7 @@ typedef union
     u8 ip_version_and_header_length;
 
     /* Type of service. */
-    u8 tos;
+    ip_dscp_t tos;
 
     /* Total layer 3 packet length including this header. */
     u16 length;
@@ -188,28 +194,30 @@ typedef union
 #define IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS \
   ((4 << 4) | (sizeof (ip4_header_t) / sizeof (u32)))
 
-always_inline int
-ip4_get_fragment_offset (ip4_header_t * i)
+#define IP4_ROUTER_ALERT_OPTION 20
+
+always_inline u16
+ip4_get_fragment_offset (const ip4_header_t * i)
 {
   return clib_net_to_host_u16 (i->flags_and_fragment_offset) & 0x1fff;
 }
 
-always_inline int
-ip4_get_fragment_more (ip4_header_t * i)
+always_inline u16
+ip4_get_fragment_more (const ip4_header_t * i)
 {
   return clib_net_to_host_u16 (i->flags_and_fragment_offset) &
     IP4_HEADER_FLAG_MORE_FRAGMENTS;
 }
 
 always_inline int
-ip4_is_fragment (ip4_header_t * i)
+ip4_is_fragment (const ip4_header_t * i)
 {
   return (i->flags_and_fragment_offset &
          clib_net_to_host_u16 (0x1fff | IP4_HEADER_FLAG_MORE_FRAGMENTS));
 }
 
 always_inline int
-ip4_is_first_fragment (ip4_header_t * i)
+ip4_is_first_fragment (const ip4_header_t * i)
 {
   return (i->flags_and_fragment_offset &
          clib_net_to_host_u16 (0x1fff | IP4_HEADER_FLAG_MORE_FRAGMENTS)) ==
@@ -218,13 +226,13 @@ ip4_is_first_fragment (ip4_header_t * i)
 
 /* Fragment offset in bytes. */
 always_inline int
-ip4_get_fragment_offset_bytes (ip4_header_t * i)
+ip4_get_fragment_offset_bytes (const ip4_header_t * i)
 {
   return 8 * ip4_get_fragment_offset (i);
 }
 
 always_inline int
-ip4_header_bytes (ip4_header_t * i)
+ip4_header_bytes (const ip4_header_t * i)
 {
   return sizeof (u32) * (i->ip_version_and_header_length & 0xf);
 }
@@ -256,6 +264,70 @@ ip4_header_checksum (ip4_header_t * i)
   return csum;
 }
 
+always_inline void
+ip4_header_set_dscp (ip4_header_t * ip4, ip_dscp_t dscp)
+{
+  ip4->tos &= ~0xfc;
+  /* not masking the dscp value to save th instruction
+   * it shouldn't b necessary since the argument is an enum
+   * whose range is therefore constrained in the CP. in the
+   * DP it will have been taken from another packet, so again
+   * constrained in  value */
+  ip4->tos |= dscp << IP_PACKET_TC_FIELD_DSCP_BIT_SHIFT;
+}
+
+always_inline void
+ip4_header_set_ecn (ip4_header_t * ip4, ip_ecn_t ecn)
+{
+  ip4->tos &= ~IP_PACKET_TC_FIELD_ECN_MASK;
+  ip4->tos |= ecn;
+}
+
+always_inline void
+ip4_header_set_ecn_w_chksum (ip4_header_t * ip4, ip_ecn_t ecn)
+{
+  ip_csum_t sum = ip4->checksum;
+  u8 old = ip4->tos;
+  u8 new = (old & ~IP_PACKET_TC_FIELD_ECN_MASK) | ecn;
+
+  sum = ip_csum_update (sum, old, new, ip4_header_t, tos);
+  ip4->checksum = ip_csum_fold (sum);
+  ip4->tos = new;
+}
+
+always_inline ip_dscp_t
+ip4_header_get_dscp (const ip4_header_t * ip4)
+{
+  return (ip4->tos >> IP_PACKET_TC_FIELD_DSCP_BIT_SHIFT);
+}
+
+always_inline ip_ecn_t
+ip4_header_get_ecn (const ip4_header_t * ip4)
+{
+  return (ip4->tos & IP_PACKET_TC_FIELD_ECN_MASK);
+}
+
+always_inline void
+ip4_header_set_df (ip4_header_t * ip4)
+{
+  ip4->flags_and_fragment_offset |=
+    clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
+}
+
+always_inline void
+ip4_header_clear_df (ip4_header_t * ip4)
+{
+  ip4->flags_and_fragment_offset &=
+    ~clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
+}
+
+always_inline u8
+ip4_header_get_df (const ip4_header_t * ip4)
+{
+  return (! !(ip4->flags_and_fragment_offset &
+             clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT)));
+}
+
 static inline uword
 ip4_header_checksum_is_valid (ip4_header_t * i)
 {
@@ -307,7 +379,7 @@ do {                                                                        \
 } while (0)
 
 always_inline uword
-ip4_address_is_multicast (ip4_address_t * a)
+ip4_address_is_multicast (const ip4_address_t * a)
 {
   return (a->data[0] & 0xf0) == 0xe0;
 }
@@ -321,9 +393,10 @@ ip4_multicast_address_set_for_group (ip4_address_t * a,
 }
 
 always_inline void
-ip4_multicast_ethernet_address (u8 * ethernet_address, ip4_address_t * a)
+ip4_multicast_ethernet_address (u8 * ethernet_address,
+                               const ip4_address_t * a)
 {
-  u8 *d = a->as_u8;
+  const u8 *d = a->as_u8;
 
   ethernet_address[0] = 0x01;
   ethernet_address[1] = 0x00;