packets: New packet_set_*() helper functions.
authorEthan Jackson <ethan@nicira.com>
Fri, 16 Dec 2011 01:58:23 +0000 (17:58 -0800)
committerEthan Jackson <ethan@nicira.com>
Tue, 10 Jan 2012 22:30:15 +0000 (14:30 -0800)
This commit pulls code used to modify L3 and L4 header fields
from dp_netdev into the packet library.  An additional user will
be added in a future commit.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
lib/dpif-netdev.c
lib/packets.c
lib/packets.h

index 4ef2e3b4605607ec76d622bbd8c853ff816afe03..f1d49b6982e32673d07ce54e4ac22ca911f6683b 100644 (file)
@@ -1052,109 +1052,6 @@ dp_netdev_set_dl(struct ofpbuf *packet, const struct ovs_key_ethernet *eth_key)
     memcpy(eh->eth_dst, eth_key->eth_dst, sizeof eh->eth_dst);
 }
 
-static void
-dp_netdev_set_ip_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr)
-{
-    struct ip_header *nh = packet->l3;
-
-    if (nh->ip_proto == IPPROTO_TCP && packet->l7) {
-        struct tcp_header *th = packet->l4;
-        th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr);
-    } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) {
-        struct udp_header *uh = packet->l4;
-        if (uh->udp_csum) {
-            uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr);
-            if (!uh->udp_csum) {
-                uh->udp_csum = htons(0xffff);
-            }
-        }
-    }
-    nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr);
-    *addr = new_addr;
-}
-
-static void
-dp_netdev_set_ip_tos(struct ip_header *nh, uint8_t new_tos)
-{
-    uint8_t *field = &nh->ip_tos;
-
-    nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
-                                   htons((uint16_t) new_tos));
-    *field = new_tos;
-}
-
-static void
-dp_netdev_set_ip_ttl(struct ip_header *nh, uint8_t new_ttl)
-{
-    uint8_t *field = &nh->ip_ttl;
-
-    nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
-                                   htons(new_ttl << 8));
-    *field = new_ttl;
-}
-
-static void
-dp_netdev_set_ipv4(struct ofpbuf *packet, const struct ovs_key_ipv4 *ipv4_key)
-{
-    struct ip_header *nh = packet->l3;
-
-    if (nh->ip_src != ipv4_key->ipv4_src) {
-        dp_netdev_set_ip_addr(packet, &nh->ip_src, ipv4_key->ipv4_src);
-    }
-    if (nh->ip_dst != ipv4_key->ipv4_dst) {
-        dp_netdev_set_ip_addr(packet, &nh->ip_dst, ipv4_key->ipv4_dst);
-    }
-    if (nh->ip_tos != ipv4_key->ipv4_tos) {
-        dp_netdev_set_ip_tos(nh, ipv4_key->ipv4_tos);
-    }
-    if (nh->ip_ttl != ipv4_key->ipv4_ttl) {
-        dp_netdev_set_ip_ttl(nh, ipv4_key->ipv4_ttl);
-    }
-}
-
-static void
-dp_netdev_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
-{
-    *csum = recalc_csum16(*csum, *port, new_port);
-    *port = new_port;
-}
-
-static void
-dp_netdev_set_tcp_port(struct ofpbuf *packet, const struct ovs_key_tcp *tcp_key)
-{
-    struct tcp_header *th = packet->l4;
-
-    if (th->tcp_src != tcp_key->tcp_src) {
-        dp_netdev_set_port(&th->tcp_src, tcp_key->tcp_src, &th->tcp_csum);
-    }
-    if (th->tcp_dst != tcp_key->tcp_dst) {
-        dp_netdev_set_port(&th->tcp_dst, tcp_key->tcp_dst, &th->tcp_csum);
-    }
-}
-
-static void
-dp_netdev_set_udp_port(struct ofpbuf *packet, const struct ovs_key_udp *udp_key)
-{
-    struct udp_header *uh = packet->l4;
-
-    if (uh->udp_csum) {
-        if (uh->udp_src != udp_key->udp_src) {
-            dp_netdev_set_port(&uh->udp_src, udp_key->udp_src, &uh->udp_csum);
-        }
-
-        if (uh->udp_dst != udp_key->udp_dst) {
-            dp_netdev_set_port(&uh->udp_dst, udp_key->udp_dst, &uh->udp_csum);
-        }
-
-        if (!uh->udp_csum) {
-            uh->udp_csum = htons(0xffff);
-        }
-    } else {
-        uh->udp_src = udp_key->udp_src;
-        uh->udp_dst = udp_key->udp_dst;
-    }
-}
-
 static void
 dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
                       uint16_t out_port)
@@ -1249,6 +1146,10 @@ static void
 execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
 {
     enum ovs_key_attr type = nl_attr_type(a);
+    const struct ovs_key_ipv4 *ipv4_key;
+    const struct ovs_key_tcp *tcp_key;
+    const struct ovs_key_udp *udp_key;
+
     switch (type) {
     case OVS_KEY_ATTR_TUN_ID:
     case OVS_KEY_ATTR_PRIORITY:
@@ -1261,18 +1162,19 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
         break;
 
     case OVS_KEY_ATTR_IPV4:
-        dp_netdev_set_ipv4(packet,
-                   nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4)));
+        ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
+        packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst,
+                        ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl);
         break;
 
     case OVS_KEY_ATTR_TCP:
-        dp_netdev_set_tcp_port(packet,
-                   nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp)));
+        tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
+        packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst);
         break;
 
      case OVS_KEY_ATTR_UDP:
-        dp_netdev_set_udp_port(packet,
-                   nl_attr_get_unspec(a, sizeof(struct ovs_key_udp)));
+        udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
+        packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst);
         break;
 
      case OVS_KEY_ATTR_UNSPEC:
index 254817429d422460a64af03da4c2f96f9dacc118..eaf3e43f4c1cb86d5bbe1f10cfbc7135b9674ecd 100644 (file)
@@ -22,6 +22,7 @@
 #include <netinet/in.h>
 #include <stdlib.h>
 #include "byte-order.h"
+#include "csum.h"
 #include "dynamic-string.h"
 #include "ofpbuf.h"
 
@@ -377,3 +378,103 @@ snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
 
     return payload;
 }
+
+static void
+packet_set_ipv4_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr)
+{
+    struct ip_header *nh = packet->l3;
+
+    if (nh->ip_proto == IPPROTO_TCP && packet->l7) {
+        struct tcp_header *th = packet->l4;
+
+        th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr);
+    } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) {
+        struct udp_header *uh = packet->l4;
+
+        if (uh->udp_csum) {
+            uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr);
+            if (!uh->udp_csum) {
+                uh->udp_csum = htons(0xffff);
+            }
+        }
+    }
+    nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr);
+    *addr = new_addr;
+}
+
+/* Modifies the IPv4 header fields of 'packet' to be consistent with 'src',
+ * 'dst', 'tos', and 'ttl'.  Updates 'packet''s L4 checksums as appropriate.
+ * 'packet' must contain a valid IPv4 packet with correctly populated l[347]
+ * markers. */
+void
+packet_set_ipv4(struct ofpbuf *packet, ovs_be32 src, ovs_be32 dst,
+                uint8_t tos, uint8_t ttl)
+{
+    struct ip_header *nh = packet->l3;
+
+    if (nh->ip_src != src) {
+        packet_set_ipv4_addr(packet, &nh->ip_src, src);
+    }
+
+    if (nh->ip_dst != dst) {
+        packet_set_ipv4_addr(packet, &nh->ip_dst, dst);
+    }
+
+    if (nh->ip_tos != tos) {
+        uint8_t *field = &nh->ip_tos;
+
+        nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field),
+                                    htons((uint16_t) tos));
+        *field = tos;
+    }
+
+    if (nh->ip_ttl != ttl) {
+        uint8_t *field = &nh->ip_ttl;
+
+        nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
+                                    htons(ttl << 8));
+        *field = ttl;
+    }
+}
+
+static void
+packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
+{
+    if (*port != new_port) {
+        *csum = recalc_csum16(*csum, *port, new_port);
+        *port = new_port;
+    }
+}
+
+/* Sets the TCP source and destination port ('src' and 'dst' respectively) of
+ * the TCP header contained in 'packet'.  'packet' must be a valid TCP packet
+ * with its l4 marker properly populated. */
+void
+packet_set_tcp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst)
+{
+    struct tcp_header *th = packet->l4;
+
+    packet_set_port(&th->tcp_src, src, &th->tcp_csum);
+    packet_set_port(&th->tcp_dst, dst, &th->tcp_csum);
+}
+
+/* Sets the UDP source and destination port ('src' and 'dst' respectively) of
+ * the UDP header contained in 'packet'.  'packet' must be a valid UDP packet
+ * with its l4 marker properly populated. */
+void
+packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst)
+{
+    struct udp_header *uh = packet->l4;
+
+    if (uh->udp_csum) {
+        packet_set_port(&uh->udp_src, src, &uh->udp_csum);
+        packet_set_port(&uh->udp_dst, dst, &uh->udp_csum);
+
+        if (!uh->udp_csum) {
+            uh->udp_csum = htons(0xffff);
+        }
+    } else {
+        uh->udp_src = src;
+        uh->udp_dst = dst;
+    }
+}
index 16834a8b72b28a6711d8245852bd95aa6f7ae368..78ccfe90dc1c8e18038f365dc2156e3e84f0e0ce 100644 (file)
@@ -463,5 +463,9 @@ void *eth_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN],
 void *snap_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN],
                    const uint8_t eth_src[ETH_ADDR_LEN],
                    unsigned int oui, uint16_t snap_type, size_t size);
+void packet_set_ipv4(struct ofpbuf *, ovs_be32 src, ovs_be32 dst, uint8_t tos,
+                     uint8_t ttl);
+void packet_set_tcp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);
+void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);
 
 #endif /* packets.h */