For SNAT, don't store the pre-fragment L2 header before actions are applied.
[sliver-openvswitch.git] / lib / packets.h
index bad3671..7f6bd42 100644 (file)
@@ -89,6 +89,17 @@ static inline void eth_addr_random(uint8_t ea[ETH_ADDR_LEN])
     ea[0] &= ~1;                /* Unicast. */
     ea[0] |= 2;                 /* Private. */
 }
+/* Returns true if 'ea' is a reserved multicast address, that a bridge must
+ * never forward, false otherwise. */
+static inline bool eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN])
+{
+    return (ea[0] == 0x01
+            && ea[1] == 0x80
+            && ea[2] == 0xc2
+            && ea[3] == 0x00
+            && ea[4] == 0x00
+            && (ea[5] & 0xf0) == 0x00);
+}
 
 #define ETH_ADDR_FMT                                                    \
     "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8
@@ -160,9 +171,13 @@ struct vlan_eth_header {
 } __attribute__((packed));
 BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header));
 
+/* The "(void) (ip)[0]" below has no effect on the value, since it's the first
+ * argument of a comma expression, but it makes sure that 'ip' is a pointer.
+ * This is useful since a common mistake is to pass an integer instead of a
+ * pointer to IP_ARGS. */
 #define IP_FMT "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8
 #define IP_ARGS(ip)                             \
-        ((uint8_t *) ip)[0],                    \
+        ((void) (ip)[0], ((uint8_t *) ip)[0]),  \
         ((uint8_t *) ip)[1],                    \
         ((uint8_t *) ip)[2],                    \
         ((uint8_t *) ip)[3]
@@ -198,6 +213,14 @@ struct ip_header {
 };
 BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header));
 
+#define ICMP_HEADER_LEN 4
+struct icmp_header {
+    uint8_t icmp_type;
+    uint8_t icmp_code;
+    uint16_t icmp_csum;
+};
+BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header));
+
 #define UDP_HEADER_LEN 8
 struct udp_header {
     uint16_t udp_src;