aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2012-01-11 12:44:23 -0800
committerPravin B Shelar <pshelar@nicira.com>2012-01-11 12:44:23 -0800
commitc4f2731da69eaba5f4bb95583225a5399875f6fc (patch)
tree3869577f4f767efff913623dfaf8c90ba1f2036a /lib
parent2284188b69fc8d935ae1ecf9d1b939e3efbbe10b (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.c2
-rw-r--r--lib/odp-util.c65
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)
{