Now that both the kernel and userspace can handle information about the tunnel outer headers this adds userspace support for communicating between the two. At the moment userspace doesn't know how to do anything with the extra information on receive and will only generate actions containing tun_id. However, both sides know how to ignore the extra information.
Signed-off-by: Jesse Gross <je...@nicira.com> --- NEWS | 2 ++ lib/odp-util.c | 75 +++++++++++++++++++++++++++++++++++++++++-------- tests/odp.at | 12 ++++---- tests/ofproto-dpif.at | 2 +- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index ae831e3..6265e2f 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,8 @@ post-v1.8.0 - The autopath action. - Interface type "null". - Numeric values for reserved ports (see "ovs-ofctl" note above). + - Tunneling requires the version of the kernel module paired with this + release (or a newer release). v1.8.0 - xx xxx xxxx diff --git a/lib/odp-util.c b/lib/odp-util.c index 9ed17ed..ac0042c 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -925,6 +925,30 @@ parse_odp_key_attr(const char *s, const struct simap *port_names, } { + char tun_id_s[32]; + unsigned long long int flags; + int tos, ttl; + struct ovs_key_ipv4_tunnel tun_key; + int n = -1; + + if (sscanf(s, "ipv4_tunnel(tun_id=%31[x0123456789abcdefABCDEF]," + "flags=%lli,src="IP_SCAN_FMT",dst="IP_SCAN_FMT + ",tos=%i,ttl=%i)%n", tun_id_s, &flags, + IP_SCAN_ARGS(&tun_key.ipv4_src), + IP_SCAN_ARGS(&tun_key.ipv4_dst), &tos, &ttl, + &n) > 0 && n > 0) { + tun_key.tun_id = htonll(strtoull(tun_id_s, NULL, 0)); + tun_key.tun_flags = flags; + tun_key.ipv4_tos = tos; + tun_key.ipv4_ttl = ttl; + memset(&tun_key.pad, 0, sizeof tun_key.pad); + nl_msg_put_unspec(key, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key, + sizeof tun_key); + return n; + } + } + + { unsigned long long int in_port; int n = -1; @@ -1273,8 +1297,18 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow) nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, flow->skb_priority); } - if (flow->tunnel.tun_id != htonll(0)) { - nl_msg_put_be64(buf, OVS_KEY_ATTR_TUN_ID, flow->tunnel.tun_id); + if (flow->tunnel.ip_dst != 0) { + struct ovs_key_ipv4_tunnel *tun_key; + + tun_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_IPV4_TUNNEL, + sizeof *tun_key); + tun_key->tun_id = flow->tunnel.tun_id; + tun_key->ipv4_src = flow->tunnel.ip_src; + tun_key->ipv4_dst = flow->tunnel.ip_dst; + tun_key->tun_flags = 0; // XXX: Need flags + tun_key->ipv4_tos = flow->tunnel.ip_tos; + tun_key->ipv4_ttl = flow->tunnel.ip_ttl; + memset(&tun_key->pad, 0, sizeof tun_key->pad); } if (flow->in_port != OFPP_NONE && flow->in_port != OFPP_CONTROLLER) { @@ -1765,9 +1799,17 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PRIORITY; } - if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUN_ID)) { - flow->tunnel.tun_id = nl_attr_get_be64(attrs[OVS_KEY_ATTR_TUN_ID]); - expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TUN_ID; + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4_TUNNEL)) { + const struct ovs_key_ipv4_tunnel *tun_key; + + tun_key = nl_attr_get(attrs[OVS_KEY_ATTR_IPV4_TUNNEL]); + flow->tunnel.tun_id = tun_key->tun_id; + flow->tunnel.ip_src = tun_key->ipv4_src; + flow->tunnel.ip_dst = tun_key->ipv4_dst; + flow->tunnel.flags = 0; // XXX need flags + flow->tunnel.ip_tos = tun_key->ipv4_tos; + flow->tunnel.ip_ttl = tun_key->ipv4_ttl; + expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4_TUNNEL; } if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IN_PORT)) { @@ -1858,16 +1900,27 @@ commit_set_action(struct ofpbuf *odp_actions, enum ovs_key_attr key_type, } static void -commit_set_tun_id_action(const struct flow *flow, struct flow *base, +commit_set_tunnel_action(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions) { - if (base->tunnel.tun_id == flow->tunnel.tun_id) { + struct ovs_key_ipv4_tunnel tun_key; + + if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) { return; } - base->tunnel.tun_id = flow->tunnel.tun_id; - commit_set_action(odp_actions, OVS_KEY_ATTR_TUN_ID, - &base->tunnel.tun_id, sizeof(base->tunnel.tun_id)); + memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel); + + tun_key.tun_id = base->tunnel.tun_id; + tun_key.ipv4_src = base->tunnel.ip_src; + tun_key.ipv4_dst = base->tunnel.ip_dst; + tun_key.tun_flags = 0; // XXX: Need flags + tun_key.ipv4_tos = base->tunnel.ip_tos; + tun_key.ipv4_ttl = base->tunnel.ip_ttl; + memset(&tun_key.pad, 0, sizeof tun_key.pad); + + commit_set_action(odp_actions, OVS_KEY_ATTR_IPV4_TUNNEL, + &tun_key, sizeof tun_key); } static void @@ -2038,7 +2091,7 @@ void commit_odp_actions(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions) { - commit_set_tun_id_action(flow, base, odp_actions); + commit_set_tunnel_action(flow, base, odp_actions); commit_set_ether_addr_action(flow, base, odp_actions); commit_vlan_action(flow, base, odp_actions); commit_set_nw_action(flow, base, odp_actions); diff --git a/tests/odp.at b/tests/odp.at index 9617af2..3eb163e 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -30,8 +30,8 @@ in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0806),arp cat odp-base.txt echo - echo '# Valid forms with tun_id header.' - sed 's/^/tun_id(0x7f10354),/' odp-base.txt + echo '# Valid forms with tunnel header.' + sed 's/^/ipv4_tunnel(tun_id=0x7f10354,flags=0x0,src=10.10.10.10,dst=20.20.20.20,tos=0x0,ttl=64),/' odp-base.txt echo echo '# Valid forms with VLAN header.' @@ -43,14 +43,14 @@ s/$/)/' odp-base.txt sed 's/^/priority(1234),/' odp-base.txt echo - echo '# Valid forms with tun_id and VLAN headers.' - sed 's/^/tun_id(0xfedcba9876543210),/ + echo '# Valid forms with tunnel and VLAN headers.' + sed 's/^/ipv4_tunnel(tun_id=0xfedcba9876543210,flags=0x0,src=10.0.0.1,dst=10.0.0.2,tos=0x8,ttl=128),/ s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/ s/$/)/' odp-base.txt echo - echo '# Valid forms with QOS priority, tun_id, and VLAN headers.' - sed 's/^/priority(1234),tun_id(0xfedcba9876543210),/ + echo '# Valid forms with QOS priority, tunnel, and VLAN headers.' + sed 's/^/priority(1234),ipv4_tunnel(tun_id=0xfedcba9876543210,flags=0x0,src=10.0.0.1,dst=10.0.0.2,tos=0x8,ttl=128),/ s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/ s/$/)/' odp-base.txt diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 80ba333..1d9ccd9 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -227,7 +227,7 @@ in_port=5 actions=set_tunnel:5 AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) AT_CHECK([ovs-appctl ofproto/trace br0 'tun_id(0x1),in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], - [Datapath actions: set(tun_id(0x1)),1,2,set(tun_id(0x3)),3,4 + [Datapath actions: set(ipv4_tunnel(tun_id=0x1,flags=0x0,src=0.0.0.0,dst=0.0.0.0,tos=0x0,ttl=0)),1,2,set(ipv4_tunnel(tun_id=0x3,flags=0x0,src=0.0.0.0,dst=0.0.0.0,tos=0x0,ttl=0)),3,4 ]) OVS_VSWITCHD_STOP AT_CLEANUP -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev