From c97664b30f65d3a087076cb33242ffe2cc52a814 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Thu, 15 Dec 2011 17:58:23 -0800 Subject: [PATCH] packets: New packet_set_*() helper functions. 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 --- lib/dpif-netdev.c | 120 +++++----------------------------------------- lib/packets.c | 101 ++++++++++++++++++++++++++++++++++++++ lib/packets.h | 4 ++ 3 files changed, 116 insertions(+), 109 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 4ef2e3b4..f1d49b69 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -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: diff --git a/lib/packets.c b/lib/packets.c index 25481742..eaf3e43f 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -22,6 +22,7 @@ #include #include #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; + } +} diff --git a/lib/packets.h b/lib/packets.h index 16834a8b..78ccfe90 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -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 */ -- 2.30.2