On 2023/03/22 8:43, Ilya Maximets wrote: > On 3/22/23 00:41, Ilya Maximets wrote: >> On 3/15/23 07:07, Nobuhiro MIKI wrote: >>> 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)); >> >> We will overwrite the header here if segments_left + 1 is less >> than total number of specified segments. E.g. in the following >> case: srv6(segments_left=0,segs=2001:cafe::92,2001:cafe::93). >> >> One solution for this may be to create an SRV6_MAX_SEGS + 1 sized >> array and parse values there. Once all the values parsed, >> copy them into an actual header. If more than SRV6_MAX_SEGS >> values found, then fail the parsing. >> >> What do you think? >>
Thanks again for your review. In this process of generating a new header, I think it is necessary to ensure that the number of parsed segments is exactly the same as segments_left + 1. Of course, it is also necessary to check that the number of segments is less than SRV6_MAX_SEGS. 1. make sure segments_left + 1 <= SRV6_MAX_SEGS. 2. put parsed values into SRV6_MAX_SEGS + 1 sized array. 3. fail if the number of the parses values is different from segments_left + 1. >> Also, the sizeof seems incorrect here. It should be in6, not in. >> It also should be just 'sizeof *segs' to avoid any potential >> problems of this kind. OK. I'll fix it. >> >> Would be good to add a test to tests/odp.at for many segments >> parsing while segments_left is small. I'll add some test cases. >> >> And it's probably possible to avoid some code duplication here. >> E.g. (didn't test): >> >> if (strncmp(s, ",segs=", 6)) { >> return -EINVAL; >> } >> s += 6; > > We need to check &s[n] and advance n, of course. :/ > >> while (ovs_scan_len(s, &n, IPV6_SCAN_FMT, seg_s) >> && inet_pton(AF_INET6, seg_s, &seg) == 1) { >> >> ... >> >> if (s[n] == ',') { >> s++; > > n++ here. > >> } >> } _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev