diff options
-rwxr-xr-x | build-aux/extract-odp-netlink-h | 6 | ||||
-rw-r--r-- | lib/csum.c | 9 | ||||
-rw-r--r-- | lib/csum.h | 4 | ||||
-rw-r--r-- | lib/odp-execute.c | 35 | ||||
-rw-r--r-- | lib/odp-util.c | 61 | ||||
-rw-r--r-- | lib/packets.c | 35 | ||||
-rw-r--r-- | lib/packets.h | 6 |
7 files changed, 75 insertions, 81 deletions
diff --git a/build-aux/extract-odp-netlink-h b/build-aux/extract-odp-netlink-h index 111c5cbdd..907a70af0 100755 --- a/build-aux/extract-odp-netlink-h +++ b/build-aux/extract-odp-netlink-h @@ -22,10 +22,14 @@ $i\ #endif\ # Use OVS's own struct eth_addr instead of a 6-byte char array. -s,<linux/types\.h>,"openvswitch/types.h", +s,<linux/types\.h>,"openvswitch/types.h"\ +#include <netinet/in.h>, s,#.*<linux/if_ether\.h>,, s/__u8[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*\[[[:space:]]*ETH_ALEN[[:space:]]*\]/struct eth_addr \1/ +# Transform IPv6 addresses from an array to struct in6_addr +s/__be32[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*\[[[:space:]]*4[[:space:]]*\]/struct in6_addr \1/ + # Transform most Linux-specific __u<N> types into C99 uint<N>_t types, # and most Linux-specific __be<N> into Open vSwitch ovs_be<N>, # and use the appropriate userspace header. diff --git a/lib/csum.c b/lib/csum.c index 5951576c0..6419043aa 100644 --- a/lib/csum.c +++ b/lib/csum.c @@ -17,6 +17,7 @@ #include <config.h> #include "csum.h" #include "unaligned.h" +#include <netinet/in.h> #ifndef __CHECKER__ /* Returns the IP checksum of the 'n' bytes in 'data'. @@ -117,9 +118,15 @@ recalc_csum48(ovs_be16 old_csum, const struct eth_addr old_mac, * changed to contain 'new_u32[4]'. */ ovs_be16 recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4], - const ovs_be32 new_u32[4]) + const struct in6_addr *new_in6) { ovs_be16 new_csum = old_csum; +#ifndef s6_addr32 + ovs_be32 new_u32[4]; + memcpy(new_u32, new_in6, sizeof new_u32); +#else + const ovs_be32 *new_u32 = new_in6->s6_addr32; +#endif int i; for (i = 0; i < 4; ++i) { diff --git a/lib/csum.h b/lib/csum.h index fc520864d..0df313ffa 100644 --- a/lib/csum.h +++ b/lib/csum.h @@ -21,6 +21,8 @@ #include <stdint.h> #include "openvswitch/types.h" +struct in6_addr; + ovs_be16 csum(const void *, size_t); uint32_t csum_continue(uint32_t partial, const void *, size_t); ovs_be16 csum_finish(uint32_t partial); @@ -29,7 +31,7 @@ ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32); ovs_be16 recalc_csum48(ovs_be16 old_csum, const struct eth_addr old_mac, const struct eth_addr new_mac); ovs_be16 recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4], - const ovs_be32 new_u32[4]); + const struct in6_addr *); #ifndef __CHECKER__ /* Adds the 16 bits in 'new' to the partial IP checksum 'partial' and returns diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 4fcff1681..73e101661 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -116,14 +116,21 @@ odp_set_ipv4(struct dp_packet *packet, const struct ovs_key_ipv4 *key, } } -static const ovs_be32 * -mask_ipv6_addr(const ovs_16aligned_be32 *old, const ovs_be32 *addr, - const ovs_be32 *mask, ovs_be32 *masked) +static struct in6_addr * +mask_ipv6_addr(const ovs_16aligned_be32 *old, const struct in6_addr *addr, + const struct in6_addr *mask, struct in6_addr *masked) { +#ifdef s6_addr32 for (int i = 0; i < 4; i++) { - masked[i] = addr[i] | (get_16aligned_be32(&old[i]) & ~mask[i]); + masked->s6_addr32[i] = addr->s6_addr32[i] + | (get_16aligned_be32(&old[i]) & ~mask->s6_addr32[i]); } - +#else + const uint8_t *old8 = (const uint8_t *)old; + for (int i = 0; i < 16; i++) { + masked->s6_addr[i] = addr->s6_addr[i] | (old8[i] & ~mask->s6_addr[i]); + } +#endif return masked; } @@ -132,14 +139,16 @@ odp_set_ipv6(struct dp_packet *packet, const struct ovs_key_ipv6 *key, const struct ovs_key_ipv6 *mask) { struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet); - ovs_be32 sbuf[4], dbuf[4]; + struct in6_addr sbuf, dbuf; uint8_t old_tc = ntohl(get_16aligned_be32(&nh->ip6_flow)) >> 20; ovs_be32 old_fl = get_16aligned_be32(&nh->ip6_flow) & htonl(0xfffff); packet_set_ipv6( packet, - mask_ipv6_addr(nh->ip6_src.be32, key->ipv6_src, mask->ipv6_src, sbuf), - mask_ipv6_addr(nh->ip6_dst.be32, key->ipv6_dst, mask->ipv6_dst, dbuf), + mask_ipv6_addr(nh->ip6_src.be32, &key->ipv6_src, &mask->ipv6_src, + &sbuf), + mask_ipv6_addr(nh->ip6_dst.be32, &key->ipv6_dst, &mask->ipv6_dst, + &dbuf), key->ipv6_tclass | (old_tc & ~mask->ipv6_tclass), key->ipv6_label | (old_fl & ~mask->ipv6_label), key->ipv6_hlimit | (nh->ip6_hlim & ~mask->ipv6_hlimit)); @@ -228,7 +237,7 @@ odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key, if (OVS_LIKELY(ns && nd_opt)) { int bytes_remain = dp_packet_l4_size(packet) - sizeof(*ns); - ovs_be32 tgt_buf[4]; + struct in6_addr tgt_buf; struct eth_addr sll_buf = eth_addr_zero; struct eth_addr tll_buf = eth_addr_zero; @@ -254,8 +263,8 @@ odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key, } packet_set_nd(packet, - mask_ipv6_addr(ns->target.be32, - key->nd_target, mask->nd_target, tgt_buf), + mask_ipv6_addr(ns->target.be32, &key->nd_target, + &mask->nd_target, &tgt_buf), sll_buf, tll_buf); } @@ -295,7 +304,7 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a) case OVS_KEY_ATTR_IPV6: ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6)); - packet_set_ipv6(packet, ipv6_key->ipv6_src, ipv6_key->ipv6_dst, + packet_set_ipv6(packet, &ipv6_key->ipv6_src, &ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass, ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit); break; @@ -352,7 +361,7 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a) if (OVS_LIKELY(dp_packet_get_nd_payload(packet))) { const struct ovs_key_nd *nd_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd)); - packet_set_nd(packet, nd_key->nd_target, nd_key->nd_sll, + packet_set_nd(packet, &nd_key->nd_target, nd_key->nd_sll, nd_key->nd_tll); } break; diff --git a/lib/odp-util.c b/lib/odp-util.c index 427dd6566..1e70e3a89 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2059,8 +2059,8 @@ odp_mask_is_exact(enum ovs_key_attr attr, const void *mask, size_t size) && ipv6_mask->ipv6_tclass == UINT8_MAX && ipv6_mask->ipv6_hlimit == UINT8_MAX && ipv6_mask->ipv6_frag == UINT8_MAX - && ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_src) - && ipv6_mask_is_exact((const struct in6_addr *)ipv6_mask->ipv6_dst); + && ipv6_mask_is_exact(&ipv6_mask->ipv6_src) + && ipv6_mask_is_exact(&ipv6_mask->ipv6_dst); } if (attr == OVS_KEY_ATTR_TUNNEL) { return false; @@ -2210,16 +2210,6 @@ format_in6_addr(struct ds *ds, const char *name, } static void -format_ipv6(struct ds *ds, const char *name, const ovs_be32 key_[4], - const ovs_be32 (*mask_)[4], bool verbose) -{ - format_in6_addr(ds, name, - (const struct in6_addr *)key_, - mask_ ? (const struct in6_addr *)*mask_ : NULL, - verbose); -} - -static void format_ipv6_label(struct ds *ds, const char *name, ovs_be32 key, const ovs_be32 *mask, bool verbose) { @@ -2866,16 +2856,18 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, const struct ovs_key_ipv6 *key = nl_attr_get(a); const struct ovs_key_ipv6 *mask = ma ? nl_attr_get(ma) : NULL; - format_ipv6(ds, "src", key->ipv6_src, MASK(mask, ipv6_src), verbose); - format_ipv6(ds, "dst", key->ipv6_dst, MASK(mask, ipv6_dst), verbose); + format_in6_addr(ds, "src", &key->ipv6_src, MASK(mask, ipv6_src), + verbose); + format_in6_addr(ds, "dst", &key->ipv6_dst, MASK(mask, ipv6_dst), + verbose); format_ipv6_label(ds, "label", key->ipv6_label, MASK(mask, ipv6_label), verbose); format_u8u(ds, "proto", key->ipv6_proto, MASK(mask, ipv6_proto), - verbose); + verbose); format_u8x(ds, "tclass", key->ipv6_tclass, MASK(mask, ipv6_tclass), - verbose); + verbose); format_u8u(ds, "hlimit", key->ipv6_hlimit, MASK(mask, ipv6_hlimit), - verbose); + verbose); format_frag(ds, "frag", key->ipv6_frag, MASK(mask, ipv6_frag), verbose); ds_chomp(ds, ','); @@ -2941,8 +2933,8 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, const struct ovs_key_nd *mask = ma ? nl_attr_get(ma) : NULL; const struct ovs_key_nd *key = nl_attr_get(a); - format_ipv6(ds, "target", key->nd_target, MASK(mask, nd_target), - verbose); + format_in6_addr(ds, "target", &key->nd_target, MASK(mask, nd_target), + verbose); format_eth(ds, "sll", key->nd_sll, MASK(mask, nd_sll), verbose); format_eth(ds, "tll", key->nd_tll, MASK(mask, nd_tll), verbose); @@ -3241,13 +3233,6 @@ scan_in6_addr(const char *s, struct in6_addr *key, struct in6_addr *mask) } static int -scan_ipv6(const char *s, ovs_be32 (*key)[4], ovs_be32 (*mask)[4]) -{ - return scan_in6_addr(s, key ? (struct in6_addr *) *key : NULL, - mask ? (struct in6_addr *) *mask : NULL); -} - -static int scan_ipv6_label(const char *s, ovs_be32 *key, ovs_be32 *mask) { int key_, mask_; @@ -4119,8 +4104,8 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, } SCAN_END(OVS_KEY_ATTR_IPV4); SCAN_BEGIN("ipv6(", struct ovs_key_ipv6) { - SCAN_FIELD("src=", ipv6, ipv6_src); - SCAN_FIELD("dst=", ipv6, ipv6_dst); + SCAN_FIELD("src=", in6_addr, ipv6_src); + SCAN_FIELD("dst=", in6_addr, ipv6_dst); SCAN_FIELD("label=", ipv6_label, ipv6_label); SCAN_FIELD("proto=", u8, ipv6_proto); SCAN_FIELD("tclass=", u8, ipv6_tclass); @@ -4164,7 +4149,7 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, } SCAN_END(OVS_KEY_ATTR_ARP); SCAN_BEGIN("nd(", struct ovs_key_nd) { - SCAN_FIELD("target=", ipv6, nd_target); + SCAN_FIELD("target=", in6_addr, nd_target); SCAN_FIELD("sll=", eth, nd_sll); SCAN_FIELD("tll=", eth, nd_tll); } SCAN_END(OVS_KEY_ATTR_ND); @@ -4455,8 +4440,7 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms, nd_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ND, sizeof *nd_key); - memcpy(nd_key->nd_target, &data->nd_target, - sizeof nd_key->nd_target); + nd_key->nd_target = data->nd_target; nd_key->nd_sll = data->arp_sha; nd_key->nd_tll = data->arp_tha; } @@ -4986,8 +4970,7 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], const struct ovs_key_nd *nd_key; nd_key = nl_attr_get(attrs[OVS_KEY_ATTR_ND]); - memcpy(&flow->nd_target, nd_key->nd_target, - sizeof flow->nd_target); + flow->nd_target = nd_key->nd_target; flow->arp_sha = nd_key->nd_sll; flow->arp_tha = nd_key->nd_tll; if (is_mask) { @@ -5613,8 +5596,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, static void get_ipv6_key(const struct flow *flow, struct ovs_key_ipv6 *ipv6, bool is_mask) { - memcpy(ipv6->ipv6_src, &flow->ipv6_src, sizeof ipv6->ipv6_src); - memcpy(ipv6->ipv6_dst, &flow->ipv6_dst, sizeof ipv6->ipv6_dst); + ipv6->ipv6_src = flow->ipv6_src; + ipv6->ipv6_dst = flow->ipv6_dst; ipv6->ipv6_label = flow->ipv6_label; ipv6->ipv6_proto = flow->nw_proto; ipv6->ipv6_tclass = flow->nw_tos; @@ -5625,8 +5608,8 @@ get_ipv6_key(const struct flow *flow, struct ovs_key_ipv6 *ipv6, bool is_mask) static void put_ipv6_key(const struct ovs_key_ipv6 *ipv6, struct flow *flow, bool is_mask) { - memcpy(&flow->ipv6_src, ipv6->ipv6_src, sizeof flow->ipv6_src); - memcpy(&flow->ipv6_dst, ipv6->ipv6_dst, sizeof flow->ipv6_dst); + flow->ipv6_src = ipv6->ipv6_src; + flow->ipv6_dst = ipv6->ipv6_dst; flow->ipv6_label = ipv6->ipv6_label; flow->nw_proto = ipv6->ipv6_proto; flow->nw_tos = ipv6->ipv6_tclass; @@ -5748,7 +5731,7 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow, static void get_nd_key(const struct flow *flow, struct ovs_key_nd *nd) { - memcpy(nd->nd_target, &flow->nd_target, sizeof flow->nd_target); + nd->nd_target = flow->nd_target; /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */ nd->nd_sll = flow->arp_sha; nd->nd_tll = flow->arp_tha; @@ -5757,7 +5740,7 @@ get_nd_key(const struct flow *flow, struct ovs_key_nd *nd) static void put_nd_key(const struct ovs_key_nd *nd, struct flow *flow) { - memcpy(&flow->nd_target, nd->nd_target, sizeof flow->nd_target); + flow->nd_target = nd->nd_target; /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */ flow->arp_sha = nd->nd_sll; flow->arp_tha = nd->nd_tll; diff --git a/lib/packets.c b/lib/packets.c index 13a063ab0..fa70df6cf 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -960,7 +960,8 @@ packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr) static void packet_update_csum128(struct dp_packet *packet, uint8_t proto, - ovs_16aligned_be32 addr[4], const ovs_be32 new_addr[4]) + ovs_16aligned_be32 addr[4], + const struct in6_addr *new_addr) { size_t l4_size = dp_packet_l4_size(packet); @@ -987,7 +988,8 @@ packet_update_csum128(struct dp_packet *packet, uint8_t proto, static void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto, - ovs_16aligned_be32 addr[4], const ovs_be32 new_addr[4], + ovs_16aligned_be32 addr[4], + const struct in6_addr *new_addr, bool recalculate_csum) { if (recalculate_csum) { @@ -1052,8 +1054,8 @@ packet_set_ipv4(struct dp_packet *packet, ovs_be32 src, ovs_be32 dst, * appropriate. 'packet' must contain a valid IPv6 packet with correctly * populated l[34] offsets. */ void -packet_set_ipv6(struct dp_packet *packet, const ovs_be32 src[4], - const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl, +packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src, + const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl) { struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet); @@ -1158,7 +1160,7 @@ packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code) } void -packet_set_nd(struct dp_packet *packet, const ovs_be32 target[4], +packet_set_nd(struct dp_packet *packet, const struct in6_addr *target, const struct eth_addr sll, const struct eth_addr tll) { struct ovs_nd_msg *ns; @@ -1174,9 +1176,8 @@ packet_set_nd(struct dp_packet *packet, const ovs_be32 target[4], bytes_remain -= sizeof(*ns); if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) { - packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, - ns->target.be32, - target, true); + packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target, + true); } while (bytes_remain >= ND_OPT_LEN && nd_opt->nd_opt_len != 0) { @@ -1352,19 +1353,13 @@ compose_ipv6(struct dp_packet *packet, uint8_t proto, struct ip6_hdr *nh; void *data; - /* Copy 'src' and 'dst' to temporary buffers to prevent misaligned - * accesses. */ - ovs_be32 sbuf[4], dbuf[4]; - memcpy(sbuf, src, sizeof sbuf); - memcpy(dbuf, dst, sizeof dbuf); - nh = dp_packet_l3(packet); nh->ip6_vfc = 0x60; nh->ip6_nxt = proto; nh->ip6_plen = htons(size); data = dp_packet_put_zeros(packet, size); dp_packet_set_l4(packet, data); - packet_set_ipv6(packet, sbuf, dbuf, key_tc, key_fl, key_hl); + packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl); return data; } @@ -1394,10 +1389,7 @@ compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src, nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; nd_opt->nd_opt_len = 1; - /* Copy target address to temp buffer to prevent misaligned access. */ - ovs_be32 tbuf[4]; - memcpy(tbuf, ipv6_dst->s6_addr, sizeof tbuf); - packet_set_nd(b, tbuf, eth_src, eth_addr_zero); + packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero); ns->icmph.icmp6_cksum = 0; icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); @@ -1428,10 +1420,7 @@ compose_nd_na(struct dp_packet *b, nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; nd_opt->nd_opt_len = 1; - /* Copy target address to temp buffer to prevent misaligned access. */ - ovs_be32 tbuf[4]; - memcpy(tbuf, ipv6_src->s6_addr, sizeof tbuf); - packet_set_nd(b, tbuf, eth_addr_zero, eth_src); + packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src); na->icmph.icmp6_cksum = 0; icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); diff --git a/lib/packets.h b/lib/packets.h index 0f1ad19f3..c4d379967 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1097,14 +1097,14 @@ void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos uint8_t ttl); void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr, ovs_be32 new_addr); -void packet_set_ipv6(struct dp_packet *, const ovs_be32 src[4], - const ovs_be32 dst[4], uint8_t tc, +void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src, + const struct in6_addr *dst, uint8_t tc, ovs_be32 fl, uint8_t hlmit); void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code); -void packet_set_nd(struct dp_packet *, const ovs_be32 target[4], +void packet_set_nd(struct dp_packet *, const struct in6_addr *target, const struct eth_addr sll, const struct eth_addr tll); void packet_format_tcp_flags(struct ds *, uint16_t); |