X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=lib%2Fodp-util.c;h=e82006bc797dbd04c4cda0a9c9ffe75cbb3ecef5;hb=530af29c41eb04d355e400871fa58f39002315de;hp=e7acaad85ffc075ac3e5764ea51c403c0ad2c8be;hpb=d31f1109f10e5ffb9bf266306b913ebf23781666;p=openvswitch diff --git a/lib/odp-util.c b/lib/odp-util.c index e7acaad8..e82006bc 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -19,6 +19,7 @@ #include "odp-util.h" #include #include +#include #include #include #include "byte-order.h" @@ -201,6 +202,7 @@ odp_flow_key_attr_len(uint16_t type) case ODP_KEY_ATTR_ICMP: return sizeof(struct odp_key_icmp); case ODP_KEY_ATTR_ICMPV6: return sizeof(struct odp_key_icmpv6); case ODP_KEY_ATTR_ARP: return sizeof(struct odp_key_arp); + case ODP_KEY_ATTR_ND: return sizeof(struct odp_key_nd); case ODP_KEY_ATTR_UNSPEC: case __ODP_KEY_ATTR_MAX: @@ -242,6 +244,7 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds) const struct odp_key_icmp *icmp_key; const struct odp_key_icmpv6 *icmpv6_key; const struct odp_key_arp *arp_key; + const struct odp_key_nd *nd_key; if (nl_attr_get_size(a) != odp_flow_key_attr_len(nl_attr_type(a))) { ds_put_format(ds, "bad length %zu, expected %d for: ", @@ -253,7 +256,7 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds) switch (nl_attr_type(a)) { case ODP_KEY_ATTR_TUN_ID: - ds_put_format(ds, "tun_id(%#"PRIx64")", nl_attr_get_be64(a)); + ds_put_format(ds, "tun_id(%#"PRIx64")", ntohll(nl_attr_get_be64(a))); break; case ODP_KEY_ATTR_IN_PORT: @@ -339,6 +342,25 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds) ETH_ADDR_ARGS(arp_key->arp_tha)); break; + case ODP_KEY_ATTR_ND: { + char target[INET6_ADDRSTRLEN]; + + nd_key = nl_attr_get(a); + inet_ntop(AF_INET6, nd_key->nd_target, target, sizeof target); + + ds_put_format(ds, "nd(target=%s", target); + if (!eth_addr_is_zero(nd_key->nd_sll)) { + ds_put_format(ds, ",sll="ETH_ADDR_FMT, + ETH_ADDR_ARGS(nd_key->nd_sll)); + } + if (!eth_addr_is_zero(nd_key->nd_tll)) { + ds_put_format(ds, ",tll="ETH_ADDR_FMT, + ETH_ADDR_ARGS(nd_key->nd_tll)); + } + ds_put_char(ds, ')'); + break; + } + default: format_generic_odp_key(a, ds); break; @@ -408,6 +430,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) ipv4_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV4, sizeof *ipv4_key); + memset(ipv4_key, 0, sizeof *ipv4_key); ipv4_key->ipv4_src = flow->nw_src; ipv4_key->ipv4_dst = flow->nw_dst; ipv4_key->ipv4_proto = flow->nw_proto; @@ -417,6 +440,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) ipv6_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV6, sizeof *ipv6_key); + memset(ipv6_key, 0, sizeof *ipv6_key); memcpy(ipv6_key->ipv6_src, &flow->ipv6_src, sizeof ipv6_key->ipv6_src); memcpy(ipv6_key->ipv6_dst, &flow->ipv6_dst, sizeof ipv6_key->ipv6_dst); ipv6_key->ipv6_proto = flow->nw_proto; @@ -426,6 +450,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) arp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ARP, sizeof *arp_key); + memset(arp_key, 0, sizeof *arp_key); arp_key->arp_sip = flow->nw_src; arp_key->arp_tip = flow->nw_dst; arp_key->arp_op = htons(flow->nw_proto); @@ -466,6 +491,18 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) sizeof *icmpv6_key); icmpv6_key->icmpv6_type = ntohs(flow->tp_src); icmpv6_key->icmpv6_code = ntohs(flow->tp_dst); + + if (icmpv6_key->icmpv6_type == ND_NEIGHBOR_SOLICIT + || icmpv6_key->icmpv6_type == ND_NEIGHBOR_ADVERT) { + struct odp_key_nd *nd_key; + + nd_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ND, + sizeof *nd_key); + memcpy(nd_key->nd_target, &flow->nd_target, + sizeof nd_key->nd_target); + memcpy(nd_key->nd_sll, flow->arp_sha, ETH_ADDR_LEN); + memcpy(nd_key->nd_tll, flow->arp_tha, ETH_ADDR_LEN); + } } } } @@ -494,6 +531,7 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, const struct odp_key_icmp *icmp_key; const struct odp_key_icmpv6 *icmpv6_key; const struct odp_key_arp *arp_key; + const struct odp_key_nd *nd_key; uint16_t type = nl_attr_type(nla); int len = odp_flow_key_attr_len(type); @@ -623,6 +661,17 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, memcpy(flow->arp_tha, arp_key->arp_tha, ETH_ADDR_LEN); break; + case TRANSITION(ODP_KEY_ATTR_ICMPV6, ODP_KEY_ATTR_ND): + if (flow->tp_src != htons(ND_NEIGHBOR_SOLICIT) + && flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) { + return EINVAL; + } + nd_key = nl_attr_get(nla); + memcpy(&flow->nd_target, nd_key->nd_target, sizeof flow->nd_target); + memcpy(flow->arp_sha, nd_key->nd_sll, ETH_ADDR_LEN); + memcpy(flow->arp_tha, nd_key->nd_tll, ETH_ADDR_LEN); + break; + default: if (type == ODP_KEY_ATTR_UNSPEC || prev_type == ODP_KEY_ATTR_UNSPEC) { @@ -673,11 +722,18 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, } return 0; + case ODP_KEY_ATTR_ICMPV6: + if (flow->icmp_type == htons(ND_NEIGHBOR_SOLICIT) + || flow->icmp_type == htons(ND_NEIGHBOR_ADVERT)) { + return EINVAL; + } + return 0; + case ODP_KEY_ATTR_TCP: case ODP_KEY_ATTR_UDP: case ODP_KEY_ATTR_ICMP: - case ODP_KEY_ATTR_ICMPV6: case ODP_KEY_ATTR_ARP: + case ODP_KEY_ATTR_ND: return 0; case __ODP_KEY_ATTR_MAX: