[ovs-dev] [PATCH] odp-util: Handle ipv6 in set nw action.
Pravin B Shelar
pshelar at nicira.com
Sat Jan 7 00:01:52 UTC 2012
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
More information about the dev
mailing list