This patch adds ODP actions for SRv6 and its tests.

Signed-off-by: Nobuhiro MIKI <nm...@yahoo-corp.jp>
---
 lib/odp-util.c                | 56 +++++++++++++++++++++++++++++++++++
 python/ovs/flow/odp.py        |  8 +++++
 python/ovs/tests/test_odp.py  | 16 ++++++++++
 tests/odp.at                  |  1 +
 tests/tunnel-push-pop-ipv6.at | 23 ++++++++++++++
 5 files changed, 104 insertions(+)

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/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)
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index 2cf306c67ecf..e5cfdc430a2b 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -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
-- 
2.31.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to