Add the corresponding ODP actions and tests in this patch before implementing SRv6 tunnel in userspace datapath.
Signed-off-by: Nobuhiro MIKI <[email protected]> --- include/linux/openvswitch.h | 1 + lib/odp-util.c | 56 ++++++++++++++++++++++++++++++++++++ lib/packets.h | 11 +++++++ python/ovs/flow/odp.py | 8 ++++++ python/ovs/tests/test_odp.py | 16 +++++++++++ tests/odp.at | 1 + 6 files changed, 93 insertions(+) diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index bc8f74991849..e305c331516b 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -254,6 +254,7 @@ enum ovs_vport_type { OVS_VPORT_TYPE_IP6GRE = 109, OVS_VPORT_TYPE_GTPU = 110, OVS_VPORT_TYPE_BAREUDP = 111, /* Bareudp tunnel. */ + OVS_VPORT_TYPE_SRV6 = 112, /* SRv6 tunnel. */ __OVS_VPORT_TYPE_MAX }; diff --git a/lib/odp-util.c b/lib/odp-util.c index dbd4554d0626..75f4d5242183 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -714,6 +714,24 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) ds_put_char(ds, ')'); } + ds_put_char(ds, ')'); + } else if (data->tnl_type == OVS_VPORT_TYPE_SRV6) { + const struct srv6_base_hdr *srh; + struct in6_addr *segs; + int nr_segs; + int i; + + srh = (const struct srv6_base_hdr *) l4; + segs = ALIGNED_CAST(struct in6_addr *, srh + 1); + nr_segs = srh->last_entry + 1; + + ds_put_format(ds, "srv6("); + ds_put_format(ds, "segments_left=%d", srh->rt_hdr.segments_left); + ds_put_format(ds, ",segs="); + for (i = 0; i < nr_segs; i++) { + ds_put_format(ds, i > 0 ? "," : ""); + ipv6_format_addr(&segs[nr_segs - i - 1], ds); + } ds_put_char(ds, ')'); } else if (data->tnl_type == OVS_VPORT_TYPE_GRE || data->tnl_type == OVS_VPORT_TYPE_IP6GRE) { @@ -1534,6 +1552,7 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) uint8_t hwid, dir; uint32_t teid; uint8_t gtpu_flags, gtpu_msgtype; + uint8_t segments_left; if (!ovs_scan_len(s, &n, "tnl_push(tnl_port(%"SCNi32"),", &data->tnl_port)) { return -EINVAL; @@ -1775,6 +1794,43 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) tnl_type = OVS_VPORT_TYPE_GTPU; header_len = sizeof *eth + ip_len + sizeof *udp + sizeof *gtph; + } else if (ovs_scan_len(s, &n, "srv6(segments_left=%"SCNu8, + &segments_left)) { + struct srv6_base_hdr *srh = (struct srv6_base_hdr *) (ip6 + 1); + uint8_t n_segs = segments_left + 1; + char seg_s[IPV6_SCAN_LEN + 1]; + struct in6_addr *segs; + struct in6_addr seg; + + ip6->ip6_nxt = IPPROTO_ROUTING; + + srh->rt_hdr.type = IPV6_SRCRT_TYPE_4; + srh->rt_hdr.segments_left = segments_left; + srh->rt_hdr.hdrlen = 2 * n_segs; + srh->last_entry = n_segs - 1; + + tnl_type = OVS_VPORT_TYPE_SRV6; + header_len = sizeof *eth + ip_len + + sizeof *srh + 8 * srh->rt_hdr.hdrlen; + + /* Parse segment list */ + if (!ovs_scan_len(s, &n, ",segs="IPV6_SCAN_FMT, seg_s) + || inet_pton(AF_INET6, seg_s, &seg) != 1) { + return -EINVAL; + } + + segs = ALIGNED_CAST(struct in6_addr *, srh + 1); + segs += n_segs - 1; + memcpy(segs--, &seg, sizeof(struct in6_addr)); + + while (ovs_scan_len(s, &n, ","IPV6_SCAN_FMT, seg_s) + && inet_pton(AF_INET6, seg_s, &seg) == 1) { + memcpy(segs--, &seg, sizeof(struct in_addr)); + } + + if (!ovs_scan_len(s, &n, "))")) { + return -EINVAL; + } } else { return -EINVAL; } diff --git a/lib/packets.h b/lib/packets.h index abff24db016e..312e849f9f26 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1527,6 +1527,17 @@ BUILD_ASSERT_DECL(sizeof(struct vxlanhdr) == 8); #define VXLAN_F_GPE 0x4000 #define VXLAN_HF_GPE 0x04000000 +/* SRv6 protocol header */ +#define IPV6_SRCRT_TYPE_4 4 +#define SRV6_BASE_HDR_LEN 8 +struct srv6_base_hdr { + struct ip6_rt_hdr rt_hdr; + uint8_t last_entry; + uint8_t flags; + ovs_be16 tag; +}; +BUILD_ASSERT_DECL(sizeof(struct srv6_base_hdr) == SRV6_BASE_HDR_LEN); + /* Input values for PACKET_TYPE macros have to be in host byte order. * The _BE postfix indicates result is in network byte order. Otherwise result * is in host byte order. */ diff --git a/python/ovs/flow/odp.py b/python/ovs/flow/odp.py index db63afc8d64d..88aee17fb2a4 100644 --- a/python/ovs/flow/odp.py +++ b/python/ovs/flow/odp.py @@ -474,6 +474,14 @@ class ODPFlow(Flow): } ) ), + "srv6": nested_kv_decoder( + KVDecoders( + { + "segments_left": decode_int, + "segs": decode_default, + } + ) + ), } ) ), diff --git a/python/ovs/tests/test_odp.py b/python/ovs/tests/test_odp.py index f8017ca8a169..ce02d3b61998 100644 --- a/python/ovs/tests/test_odp.py +++ b/python/ovs/tests/test_odp.py @@ -452,6 +452,22 @@ def test_odp_fields(input_string, expected): ), ], ), + ( + "actions:tnl_push(header(srv6(segments_left=0,segs=2001:cafe::92)))", # noqa: E501 + [ + KeyValue( + "tnl_push", + { + "header": { + "srv6": { + "segments_left": 0, + "segs": "2001:cafe::92", + } + } + }, + ), + ], + ), ( "actions:clone(1),clone(clone(push_vlan(vid=12,pcp=0),2),1)", [ diff --git a/tests/odp.at b/tests/odp.at index 26cda2967239..dccb781a4e73 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -342,6 +342,7 @@ tnl_push(tnl_port(6),header(size=70,type=4,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:1 tnl_push(tnl_port(6),header(size=70,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=6081,csum=0x0),geneve(oam,vni=0x1c7)),out_port(1)) tnl_push(tnl_port(6),header(size=78,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=6081,csum=0x0),geneve(crit,vni=0x1c7,options({class=0xffff,type=0x80,len=4,0xa}))),out_port(1)) tnl_push(tnl_port(6),header(size=70,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=6081,csum=0xffff),geneve(vni=0x1c7)),out_port(1)) +tnl_push(tnl_port(6),header(size=78,type=112,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=43,tclass=0x0,hlimit=64),srv6(segments_left=0,segs=2001:cafe::92)),out_port(1)) ct ct(commit) ct(commit,zone=5) -- 2.31.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
