diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2012-01-11 12:44:23 -0800 |
---|---|---|
committer | Pravin B Shelar <pshelar@nicira.com> | 2012-01-11 12:44:23 -0800 |
commit | c4f2731da69eaba5f4bb95583225a5399875f6fc (patch) | |
tree | 3869577f4f767efff913623dfaf8c90ba1f2036a /lib | |
parent | 2284188b69fc8d935ae1ecf9d1b939e3efbbe10b (diff) |
odp-util: Handle ipv6 in set nw action.
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.
Bug #8758
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/dpif-netdev.c | 2 | ||||
-rw-r--r-- | lib/odp-util.c | 65 |
2 files changed, 53 insertions, 14 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index f1d49b69..ad1a39bb 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1153,6 +1153,7 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a) switch (type) { case OVS_KEY_ATTR_TUN_ID: case OVS_KEY_ATTR_PRIORITY: + case OVS_KEY_ATTR_IPV6: /* not implemented */ break; @@ -1180,7 +1181,6 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a) case OVS_KEY_ATTR_UNSPEC: case OVS_KEY_ATTR_ENCAP: case OVS_KEY_ATTR_ETHERTYPE: - case OVS_KEY_ATTR_IPV6: case OVS_KEY_ATTR_IN_PORT: case OVS_KEY_ATTR_VLAN: case OVS_KEY_ATTR_ICMP: diff --git a/lib/odp-util.c b/lib/odp-util.c index bfc1937c..ffb486ec 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1136,11 +1136,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'. */ @@ -1778,16 +1778,11 @@ 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) { - return; - } - if (base->nw_src == flow->nw_src && base->nw_dst == flow->nw_dst && base->nw_tos == flow->nw_tos && @@ -1801,15 +1796,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_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) +{ + /* Check if flow really have an IP header. */ + if (!flow->nw_proto) { + return; + } + + 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) { |