2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-05 00:35:33 +00:00

odp: Add SRv6 tunnel actions.

This patch adds ODP actions for SRv6 and its tests.

Signed-off-by: Nobuhiro MIKI <nmiki@yahoo-corp.jp>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Nobuhiro MIKI
2023-03-29 14:51:18 +09:00
committed by Ilya Maximets
parent 03fc1ad785
commit 7381fd440a
5 changed files with 127 additions and 2 deletions

View File

@@ -715,6 +715,24 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
}
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_format(ds, "))");
} else if (data->tnl_type == OVS_VPORT_TYPE_GRE ||
data->tnl_type == OVS_VPORT_TYPE_IP6GRE) {
const struct gre_base_hdr *greh;
@@ -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,57 @@ 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);
char seg_s[IPV6_SCAN_LEN + 1];
struct in6_addr *segs;
struct in6_addr seg;
uint8_t n_segs = 0;
if (segments_left + 1 > SRV6_MAX_SEGS) {
return -EINVAL;
}
ip6->ip6_nxt = IPPROTO_ROUTING;
srh->rt_hdr.hdrlen = 2 * (segments_left + 1);
srh->rt_hdr.segments_left = segments_left;
srh->rt_hdr.type = IPV6_SRCRT_TYPE_4;
srh->last_entry = segments_left;
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(")) {
return -EINVAL;
}
segs = ALIGNED_CAST(struct in6_addr *, srh + 1);
segs += segments_left;
while (ovs_scan_len(s, &n, IPV6_SCAN_FMT, seg_s)
&& inet_pton(AF_INET6, seg_s, &seg) == 1) {
if (n_segs == segments_left + 1) {
return -EINVAL;
}
memcpy(segs--, &seg, sizeof *segs);
n_segs++;
if (s[n] == ',') {
n++;
}
}
if (!ovs_scan_len(s, &n, ")))")) {
return -EINVAL;
}
if (n_segs != segments_left + 1) {
return -EINVAL;
}
} else {
return -EINVAL;
}

View File

@@ -474,6 +474,14 @@ class ODPFlow(Flow):
}
)
),
"srv6": nested_kv_decoder(
KVDecoders(
{
"segments_left": decode_int,
"segs": decode_default,
}
)
),
}
)
),

View File

@@ -452,6 +452,22 @@ def test_odp_fields(input_string, expected):
),
],
),
(
"actions:tnl_push(header(srv6(segments_left=1,segs(2001:cafe::90,2001:cafe::91))))", # noqa: E501
[
KeyValue(
"tnl_push",
{
"header": {
"srv6": {
"segments_left": 1,
"segs": "2001:cafe::90,2001:cafe::91",
}
}
},
),
],
),
(
"actions:clone(1),clone(clone(push_vlan(vid=12,pcp=0),2),1)",
[

View File

@@ -342,6 +342,8 @@ 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::90))),out_port(1))
tnl_push(tnl_port(6),header(size=110,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=2,segs(2001:cafe::90,2001:cafe::91,2001:cafe::92))),out_port(1))
ct
ct(commit)
ct(commit,zone=5)
@@ -400,8 +402,14 @@ AT_CLEANUP
AT_SETUP([OVS datapath actions parsing and formatting - invalid forms])
dnl This caused a hang in older versions.
AT_CHECK([echo 'encap_nsh@:{@' | ovstest test-odp parse-actions
], [0], [dnl
AT_DATA([actions.txt], [dnl
encap_nsh@:{@
tnl_push(tnl_port(6),header(size=94,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=2,segs(2001:cafe::90,2001:cafe::91))),out_port(1))
tnl_push(tnl_port(6),header(size=126,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=2,segs(2001:cafe::90,2001:cafe::91,2001:cafe::92,2001:cafe::93))),out_port(1))
])
AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [dnl
odp_actions_from_string: error
odp_actions_from_string: error
odp_actions_from_string: error
])
AT_CLEANUP

View File

@@ -202,6 +202,8 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \
options:remote_ip=flow options:key=123 ofport_request=5\
-- add-port int-br t5 -- set Interface t5 type=gre \
options:remote_ip=2001:cafe::92 options:key=455 options:packet_type=legacy_l3 ofport_request=6\
-- add-port int-br t6 -- set Interface t6 type=srv6 \
options:remote_ip=2001:cafe::92 ofport_request=7\
], [0])
AT_CHECK([ovs-appctl dpif/show], [0], [dnl
@@ -216,12 +218,15 @@ dummy@ovs-dummy: hit:0 missed:0
t3 4/4789: (vxlan: csum=true, out_key=flow, remote_ip=2001:cafe::93)
t4 5/6081: (geneve: key=123, remote_ip=flow)
t5 6/3: (gre: key=455, packet_type=legacy_l3, remote_ip=2001:cafe::92)
t6 7/6: (srv6: remote_ip=2001:cafe::92)
])
AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
Listening ports:
genev_sys_6081 (6081) ref_cnt=1
gre_sys (3) ref_cnt=2
srv6_sys (6) ref_cnt=1
srv6_sys (6) ref_cnt=1
vxlan_sys_4789 (4789) ref_cnt=2
])
@@ -363,6 +368,8 @@ AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
Listening ports:
genev_sys_6081 (6081) ref_cnt=1
gre_sys (3) ref_cnt=2
srv6_sys (6) ref_cnt=1
srv6_sys (6) ref_cnt=1
vxlan_sys_4789 (4789) ref_cnt=2
])
@@ -384,6 +391,12 @@ AT_CHECK([tail -1 stdout], [0],
[Datapath actions: tnl_pop(6081)
])
dnl Check SRv6 tunnel pop
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=4,tclass=0x0,hlimit=64)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: tnl_pop(6)
])
dnl Check VXLAN tunnel push
AT_CHECK([ovs-ofctl add-flow int-br action=2])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
@@ -405,6 +418,13 @@ AT_CHECK([tail -1 stdout], [0],
[Datapath actions: tnl_push(tnl_port(3),header(size=62,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x2000,proto=0x6558),key=0x1c8)),out_port(100)),1
])
dnl Check SRv6 tunnel push
AT_CHECK([ovs-ofctl add-flow int-br action=7])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: pop_eth,tnl_push(tnl_port(6),header(size=78,type=112,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,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(100)),1
])
dnl Check Geneve tunnel push
AT_CHECK([ovs-ofctl add-flow int-br "actions=set_field:2001:cafe::92->tun_ipv6_dst,5"])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
@@ -510,6 +530,8 @@ AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
Listening ports:
genev_sys_6081 (6081) ref_cnt=1
gre_sys (3) ref_cnt=1
srv6_sys (6) ref_cnt=1
srv6_sys (6) ref_cnt=1
vxlan_sys_4789 (4789) ref_cnt=1
vxlan_sys_4790 (4790) ref_cnt=1
])
@@ -518,6 +540,7 @@ AT_CHECK([ovs-vsctl del-port int-br t1 \
-- del-port int-br t2 \
-- del-port int-br t4 \
-- del-port int-br t5 \
-- del-port int-br t6 \
], [0])
dnl Check tunnel lookup entries after deleting all remaining tunnel ports