Rather than silently skipping ipv6 action generation, following patch generates OVS_ACTION_ATTR_SET action for ipv6. Datapath which do not support ipv6 action can reject this action.
--- lib/odp-util.c | 63 +++++++++++++++++++++++++++++++++++++++++------- lib/packets.h | 10 +++++++ tests/ofproto-dpif.at | 13 ++++++++++ 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index 490d35e..a7a41d6 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1149,11 +1149,11 @@ odp_flow_key_from_string(const char *s, const struct shash *port_names, } static uint8_t -ovs_to_odp_frag(uint8_t ovs_frag) +ovs_to_odp_frag(uint8_t nw_frag) { - return (ovs_frag & FLOW_NW_FRAG_LATER ? OVS_FRAG_TYPE_LATER - : ovs_frag & FLOW_NW_FRAG_ANY ? OVS_FRAG_TYPE_FIRST - : OVS_FRAG_TYPE_NONE); + return (nw_frag == 0 ? OVS_FRAG_TYPE_NONE + : nw_frag == FLOW_NW_FRAG_ANY ? OVS_FRAG_TYPE_FIRST + : OVS_FRAG_TYPE_LATER); } /* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'. */ @@ -1791,13 +1791,12 @@ commit_vlan_action(const struct flow *flow, struct flow *base, } static void -commit_set_nw_action(const struct flow *flow, struct flow *base, +commit_set_ipv4_action(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions) { struct ovs_key_ipv4 ipv4_key; - if (base->dl_type != htons(ETH_TYPE_IP) || - !base->nw_src || !base->nw_dst) { + if (!base->nw_src || !base->nw_dst) { return; } @@ -1814,15 +1813,59 @@ commit_set_nw_action(const struct flow *flow, struct flow *base, ipv4_key.ipv4_tos = base->nw_tos = flow->nw_tos; ipv4_key.ipv4_ttl = base->nw_ttl = flow->nw_ttl; ipv4_key.ipv4_proto = base->nw_proto; - ipv4_key.ipv4_frag = (base->nw_frag == 0 ? OVS_FRAG_TYPE_NONE - : base->nw_frag == FLOW_NW_FRAG_ANY - ? OVS_FRAG_TYPE_FIRST : OVS_FRAG_TYPE_LATER); + ipv4_key.ipv4_frag = ovs_to_odp_frag(base->nw_frag); commit_set_action(odp_actions, OVS_KEY_ATTR_IPV4, &ipv4_key, sizeof(ipv4_key)); } static void +commit_set_ipv6_action(const struct flow *flow, struct flow *base, + struct ofpbuf *odp_actions) +{ + struct ovs_key_ipv6 ipv6_key; + + if (ipv6_addr_is_zero(&base->ipv6_src) || + ipv6_addr_is_zero(&base->ipv6_dst)) { + return; + } + + if (ipv6_addr_equals(&base->ipv6_src, &flow->ipv6_src) && + ipv6_addr_equals(&base->ipv6_dst, &flow->ipv6_dst) && + base->ipv6_label == flow->ipv6_label && + base->nw_tos == flow->nw_tos && + base->nw_ttl == flow->nw_ttl && + base->nw_frag == flow->nw_frag) { + return; + } + + base->ipv6_src = flow->ipv6_src; + memcpy(&ipv6_key.ipv6_src, &base->ipv6_src, sizeof(ipv6_key.ipv6_src)); + base->ipv6_dst = flow->ipv6_dst; + memcpy(&ipv6_key.ipv6_dst, &base->ipv6_dst, sizeof(ipv6_key.ipv6_dst)); + + ipv6_key.ipv6_label = base->ipv6_label = flow->ipv6_label; + ipv6_key.ipv6_tclass = base->nw_tos = flow->nw_tos; + ipv6_key.ipv6_hlimit = base->nw_ttl = flow->nw_ttl; + ipv6_key.ipv6_proto = base->nw_proto; + ipv6_key.ipv6_frag = ovs_to_odp_frag(base->nw_frag); + + commit_set_action(odp_actions, OVS_KEY_ATTR_IPV6, + &ipv6_key, sizeof(ipv6_key)); +} + +static void +commit_set_nw_action(const struct flow *flow, struct flow *base, + struct ofpbuf *odp_actions) +{ + if (base->dl_type == htons(ETH_TYPE_IP)) { + commit_set_ipv4_action(flow, base, odp_actions); + } else if (base->dl_type == htons(ETH_TYPE_IPV6)) { + commit_set_ipv6_action(flow, base, odp_actions); + } +} + +static void commit_set_port_action(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions) { diff --git a/lib/packets.h b/lib/packets.h index 16834a8..628f011 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -464,4 +464,14 @@ 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); +static inline int ipv6_addr_is_zero(const struct in6_addr *addr) +{ + const uint32_t *a = (const uint32_t *)&addr->s6_addr[0]; + int i, ret = 0; + + for (i = 0; i < 4; i++) { + ret += a[i]; + } + return !ret; +} #endif /* packets.h */ diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index d58c531..5abec02 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -1,5 +1,18 @@ AT_BANNER([ofproto-dpif]) +AT_SETUP([ofproto-dpif - odp-ipv6 action]) +OVS_VSWITCHD_START +AT_DATA([flows.txt], [dnl +in_port=3 action=mod_nw_tos:0x80,output:2 +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no),tcp(src=12345,dst=80)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x80,hlimit=128,frag=no)),2 +]) +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto-dpif - resubmit]) OVS_VSWITCHD_START AT_DATA([flows.txt], [dnl -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev