From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 89CCA42BFC; Thu, 1 Jun 2023 04:26:20 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7AD31406B3; Thu, 1 Jun 2023 04:26:20 +0200 (CEST) Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) by mails.dpdk.org (Postfix) with ESMTP id EA9B8406A2 for ; Thu, 1 Jun 2023 04:26:18 +0200 (CEST) Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-3f7f864525fso2573231cf.1 for ; Wed, 31 May 2023 19:26:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685586378; x=1688178378; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=aw/XBvI72ke0tGQPI8Pw7VUZGy21PndpLuISUoUEUuo=; b=WWewa/qprUP/2isr8KgpBs8upYliOZfOcKCe5bjS0czPfM3pVW1YPoCna1REDjdIR+ XUSq0QlBIKe6hXQZwMBIthgLgH1pWr7PGEPd6B6sZ2yMDagH0lbKLqHn3liE5aPaTCR6 7nMBYTDMaCCgxiG0NWntSpa+9oO/QZdQt8jSINZyBcnqIcMnfDu26TfqBvphl9ZZV+Tr UjulHiOHE+L/4DPHc1snOkpuWLtUiRZ0VZSdmwDAcHJ9fDIfmQWFNKJRemibJEbtzArf 5/c+L40Kp2KDkQPa0R2gI/6SyoiqG6j00TYbIZKkdLmC50aWO1HcquAluiUobK95ja9F gg8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685586378; x=1688178378; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aw/XBvI72ke0tGQPI8Pw7VUZGy21PndpLuISUoUEUuo=; b=Ebgg1XghiSWCiUDY4L6vcf/Py2VaZb2pZcHIUF6ZVswA6XH3yA7Q0y+nikOQXgrno3 e0KZgjN+0zCAb9UaCbO0JbK/wm0Zfw+rO6TPbim+5IxgAttN9SqRvjIx+zP1MnjWqC2i QBgYEC6HWLlwHI/nAqrSCsBeKVc1tb/O/r64M9GNT/+9JFbpIMhP5Ey6qYbvVXpyNTsX d+rL58t+7QyOH70YjXvKeAP8TeREWt8chPSsH05CYJRjaJ6gr1WJjuxWxiHIxedPQkzr FkoD1g7ipXCmifv0UDrYH0FnBIE8sw/gvxJDeT1Lj/3zQtlrEOMDqAWadp7ISiZanPdr 18qw== X-Gm-Message-State: AC+VfDwNHX7o/qA9D1BjZTCmxf0GGE7TvHgrDXGCEz/oE8XTprqcCPKZ nHaGD/IJJIrbqR6gh8BfRrMVK28Y89BMW/i6mLm+WRvtBuHwcA== X-Google-Smtp-Source: ACHHUZ7mV1/F9qTTm1nfbNUuXTrN4nQZgR0JtT0cVmRGdRx0AfuPxb3TYv7lQ5LSOftXUgWoQV1WXpMcYBGZSMKFcUg= X-Received: by 2002:a05:622a:1004:b0:3f6:833b:2368 with SMTP id d4-20020a05622a100400b003f6833b2368mr10572824qte.46.1685586378089; Wed, 31 May 2023 19:26:18 -0700 (PDT) MIME-Version: 1.0 References: <20230518155654.1756576-1-amitprakashs@marvell.com> <20230531113743.1929627-1-amitprakashs@marvell.com> <20230531113743.1929627-2-amitprakashs@marvell.com> In-Reply-To: <20230531113743.1929627-2-amitprakashs@marvell.com> From: Nithin Dabilpuram Date: Thu, 1 Jun 2023 07:56:05 +0530 Message-ID: Subject: Re: [PATCH v3 2/3] lib: add IPv6 rewrite node To: Amit Prakash Shukla Cc: Jerin Jacob , Kiran Kumar K , Nithin Dabilpuram , Pavan Nikhilesh , dev@dpdk.org, skori@marvell.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Series Acked-by: Nithin Dabilpuram On Wed, May 31, 2023 at 5:08=E2=80=AFPM Amit Prakash Shukla wrote: > > Similar to IPv4 rewrite node, patch adds IPv6 rewrite node. > > Signed-off-by: Amit Prakash Shukla > --- > v2: > - Performance related changes > > v3: > - Removing redundant dynamic variable > > doc/guides/prog_guide/graph_lib.rst | 8 + > lib/node/ethdev_ctrl.c | 13 ++ > lib/node/ip6_rewrite.c | 331 ++++++++++++++++++++++++++++ > lib/node/ip6_rewrite_priv.h | 69 ++++++ > lib/node/meson.build | 1 + > 5 files changed, 422 insertions(+) > create mode 100644 lib/node/ip6_rewrite.c > create mode 100644 lib/node/ip6_rewrite_priv.h > > diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/= graph_lib.rst > index 1f70d63628..841cabe259 100644 > --- a/doc/guides/prog_guide/graph_lib.rst > +++ b/doc/guides/prog_guide/graph_lib.rst > @@ -401,6 +401,14 @@ On LPM lookup failure, objects are redirected to pkt= _drop node. > To achieve home run, node use ``rte_node_stream_move()`` as mentioned in= above > sections. > > +ip6_rewrite > +~~~~~~~~~~~ > +This node gets packets from ``ip6_lookup`` node with next-hop id for eac= h > +packet is embedded in ``node_mbuf_priv1(mbuf)->nh``. This id is used > +to determine the L2 header to be written to the packet before sending > +the packet out to a particular ethdev_tx node. > +``rte_node_ip6_rewrite_add()`` is control path API to add next-hop info. > + > null > ~~~~ > This node ignores the set of objects passed to it and reports that all a= re > diff --git a/lib/node/ethdev_ctrl.c b/lib/node/ethdev_ctrl.c > index 37df0431b8..ea7dc8210b 100644 > --- a/lib/node/ethdev_ctrl.c > +++ b/lib/node/ethdev_ctrl.c > @@ -12,6 +12,7 @@ > #include "ethdev_rx_priv.h" > #include "ethdev_tx_priv.h" > #include "ip4_rewrite_priv.h" > +#include "ip6_rewrite_priv.h" > #include "node_private.h" > > static struct ethdev_ctrl { > @@ -23,6 +24,7 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf= , uint16_t nb_confs, > uint16_t nb_graphs) > { > struct rte_node_register *ip4_rewrite_node; > + struct rte_node_register *ip6_rewrite_node; > struct ethdev_tx_node_main *tx_node_data; > uint16_t tx_q_used, rx_q_used, port_id; > struct rte_node_register *tx_node; > @@ -33,6 +35,7 @@ rte_node_eth_config(struct rte_node_ethdev_config *conf= , uint16_t nb_confs, > uint32_t id; > > ip4_rewrite_node =3D ip4_rewrite_node_get(); > + ip6_rewrite_node =3D ip6_rewrite_node_get(); > tx_node_data =3D ethdev_tx_node_data_get(); > tx_node =3D ethdev_tx_node_get(); > for (i =3D 0; i < nb_confs; i++) { > @@ -110,6 +113,16 @@ rte_node_eth_config(struct rte_node_ethdev_config *c= onf, uint16_t nb_confs, > port_id, rte_node_edge_count(ip4_rewrite_node->id= ) - 1); > if (rc < 0) > return rc; > + > + /* Add this tx port node as next to ip6_rewrite_node */ > + rte_node_edge_update(ip6_rewrite_node->id, RTE_EDGE_ID_IN= VALID, > + &next_nodes, 1); > + /* Assuming edge id is the last one alloc'ed */ > + rc =3D ip6_rewrite_set_next( > + port_id, rte_node_edge_count(ip6_rewrite_node->id= ) - 1); > + if (rc < 0) > + return rc; > + > } > > ctrl.nb_graphs =3D nb_graphs; > diff --git a/lib/node/ip6_rewrite.c b/lib/node/ip6_rewrite.c > new file mode 100644 > index 0000000000..198d8d8820 > --- /dev/null > +++ b/lib/node/ip6_rewrite.c > @@ -0,0 +1,331 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rte_node_ip6_api.h" > + > +#include "ip6_rewrite_priv.h" > +#include "node_private.h" > + > +struct ip6_rewrite_node_ctx { > + /* Dynamic offset to mbuf priv1 */ > + int mbuf_priv1_off; > + /* Cached next index */ > + uint16_t next_index; > +}; > + > +static struct ip6_rewrite_node_main *ip6_rewrite_nm; > + > +#define IP6_REWRITE_NODE_LAST_NEXT(ctx) \ > + (((struct ip6_rewrite_node_ctx *)ctx)->next_index) > + > +#define IP6_REWRITE_NODE_PRIV1_OFF(ctx) \ > + (((struct ip6_rewrite_node_ctx *)ctx)->mbuf_priv1_off) > + > +static uint16_t > +ip6_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, > + void **objs, uint16_t nb_objs) > +{ > + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; > + struct ip6_rewrite_nh_header *nh =3D ip6_rewrite_nm->nh; > + const int dyn =3D IP6_REWRITE_NODE_PRIV1_OFF(node->ctx); > + uint16_t next0, next1, next2, next3, next_index; > + uint16_t n_left_from, held =3D 0, last_spec =3D 0; > + struct rte_ipv6_hdr *ip0, *ip1, *ip2, *ip3; > + void *d0, *d1, *d2, *d3; > + void **to_next, **from; > + rte_xmm_t priv01; > + rte_xmm_t priv23; > + int i; > + > + /* Speculative next as last next */ > + next_index =3D IP6_REWRITE_NODE_LAST_NEXT(node->ctx); > + rte_prefetch0(nh); > + > + pkts =3D (struct rte_mbuf **)objs; > + from =3D objs; > + n_left_from =3D nb_objs; > + > + for (i =3D 0; i < 4 && i < n_left_from; i++) > + rte_prefetch0(pkts[i]); > + > + /* Get stream for the speculated next node */ > + to_next =3D rte_node_next_stream_get(graph, node, next_index, nb_= objs); > + /* Update Ethernet header of pkts */ > + while (n_left_from >=3D 4) { > + if (likely(n_left_from > 7)) { > + /* Prefetch only next-mbuf struct and priv area. > + * Data need not be prefetched as we only write. > + */ > + rte_prefetch0(pkts[4]); > + rte_prefetch0(pkts[5]); > + rte_prefetch0(pkts[6]); > + rte_prefetch0(pkts[7]); > + } > + > + mbuf0 =3D pkts[0]; > + mbuf1 =3D pkts[1]; > + mbuf2 =3D pkts[2]; > + mbuf3 =3D pkts[3]; > + > + pkts +=3D 4; > + n_left_from -=3D 4; > + priv01.u64[0] =3D node_mbuf_priv1(mbuf0, dyn)->u; > + priv01.u64[1] =3D node_mbuf_priv1(mbuf1, dyn)->u; > + priv23.u64[0] =3D node_mbuf_priv1(mbuf2, dyn)->u; > + priv23.u64[1] =3D node_mbuf_priv1(mbuf3, dyn)->u; > + > + /* Update next_hop rewrite ethernet hdr on mbuf0 */ > + d0 =3D rte_pktmbuf_mtod(mbuf0, void *); > + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, > + nh[priv01.u16[0]].rewrite_len); > + > + next0 =3D nh[priv01.u16[0]].tx_node; > + ip0 =3D (struct rte_ipv6_hdr *)((uint8_t *)d0 + > + sizeof(struct rte_ether_hdr= )); > + ip0->hop_limits =3D priv01.u16[1] - 1; > + > + /* Update next_hop rewrite ethernet hdr on mbuf1 */ > + d1 =3D rte_pktmbuf_mtod(mbuf1, void *); > + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, > + nh[priv01.u16[4]].rewrite_len); > + > + next1 =3D nh[priv01.u16[4]].tx_node; > + ip1 =3D (struct rte_ipv6_hdr *)((uint8_t *)d1 + > + sizeof(struct rte_ether_hdr= )); > + ip1->hop_limits =3D priv01.u16[5] - 1; > + > + /* Update next_hop rewrite ethernet hdr on mbuf2 */ > + d2 =3D rte_pktmbuf_mtod(mbuf2, void *); > + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, > + nh[priv23.u16[0]].rewrite_len); > + next2 =3D nh[priv23.u16[0]].tx_node; > + ip2 =3D (struct rte_ipv6_hdr *)((uint8_t *)d2 + > + sizeof(struct rte_ether_hdr= )); > + ip2->hop_limits =3D priv23.u16[1] - 1; > + > + /* Update next_hop rewrite ethernet hdr on mbuf3 */ > + d3 =3D rte_pktmbuf_mtod(mbuf3, void *); > + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, > + nh[priv23.u16[4]].rewrite_len); > + > + next3 =3D nh[priv23.u16[4]].tx_node; > + ip3 =3D (struct rte_ipv6_hdr *)((uint8_t *)d3 + > + sizeof(struct rte_ether_hdr= )); > + ip3->hop_limits =3D priv23.u16[5] - 1; > + > + /* Enqueue four packets to next node */ > + rte_edge_t fix_spec =3D > + ((next_index =3D=3D next0) && (next0 =3D=3D next1= ) && > + (next1 =3D=3D next2) && (next2 =3D=3D next3)); > + > + if (unlikely(fix_spec =3D=3D 0)) { > + /* Copy things successfully speculated till now *= / > + rte_memcpy(to_next, from, last_spec * sizeof(from= [0])); > + from +=3D last_spec; > + to_next +=3D last_spec; > + held +=3D last_spec; > + last_spec =3D 0; > + > + /* next0 */ > + if (next_index =3D=3D next0) { > + to_next[0] =3D from[0]; > + to_next++; > + held++; > + } else { > + rte_node_enqueue_x1(graph, node, next0, > + from[0]); > + } > + > + /* next1 */ > + if (next_index =3D=3D next1) { > + to_next[0] =3D from[1]; > + to_next++; > + held++; > + } else { > + rte_node_enqueue_x1(graph, node, next1, > + from[1]); > + } > + > + /* next2 */ > + if (next_index =3D=3D next2) { > + to_next[0] =3D from[2]; > + to_next++; > + held++; > + } else { > + rte_node_enqueue_x1(graph, node, next2, > + from[2]); > + } > + > + /* next3 */ > + if (next_index =3D=3D next3) { > + to_next[0] =3D from[3]; > + to_next++; > + held++; > + } else { > + rte_node_enqueue_x1(graph, node, next3, > + from[3]); > + } > + > + from +=3D 4; > + > + /* Change speculation if last two are same */ > + if ((next_index !=3D next3) && (next2 =3D=3D next= 3)) { > + /* Put the current speculated node */ > + rte_node_next_stream_put(graph, node, > + next_index, held= ); > + held =3D 0; > + > + /* Get next speculated stream */ > + next_index =3D next3; > + to_next =3D rte_node_next_stream_get( > + graph, node, next_index, nb_objs)= ; > + } > + } else { > + last_spec +=3D 4; > + } > + } > + > + while (n_left_from > 0) { > + mbuf0 =3D pkts[0]; > + > + pkts +=3D 1; > + n_left_from -=3D 1; > + > + d0 =3D rte_pktmbuf_mtod(mbuf0, void *); > + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrit= e_data, > + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_le= n); > + > + next0 =3D nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; > + ip0 =3D (struct rte_ipv6_hdr *)((uint8_t *)d0 + > + sizeof(struct rte_ether_hdr= )); > + ip0->hop_limits =3D node_mbuf_priv1(mbuf0, dyn)->ttl - 1; > + > + if (unlikely(next_index ^ next0)) { > + /* Copy things successfully speculated till now *= / > + rte_memcpy(to_next, from, last_spec * sizeof(from= [0])); > + from +=3D last_spec; > + to_next +=3D last_spec; > + held +=3D last_spec; > + last_spec =3D 0; > + > + rte_node_enqueue_x1(graph, node, next0, from[0]); > + from +=3D 1; > + } else { > + last_spec +=3D 1; > + } > + } > + > + /* !!! Home run !!! */ > + if (likely(last_spec =3D=3D nb_objs)) { > + rte_node_next_stream_move(graph, node, next_index); > + return nb_objs; > + } > + > + held +=3D last_spec; > + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > + rte_node_next_stream_put(graph, node, next_index, held); > + /* Save the last next used */ > + IP6_REWRITE_NODE_LAST_NEXT(node->ctx) =3D next_index; > + > + return nb_objs; > +} > + > +static int > +ip6_rewrite_node_init(const struct rte_graph *graph, struct rte_node *no= de) > +{ > + static bool init_once; > + > + RTE_SET_USED(graph); > + RTE_BUILD_BUG_ON(sizeof(struct ip6_rewrite_node_ctx) > RTE_NODE_C= TX_SZ); > + > + if (!init_once) { > + node_mbuf_priv1_dynfield_offset =3D rte_mbuf_dynfield_reg= ister( > + &node_mbuf_priv1_dynfield_desc); > + if (node_mbuf_priv1_dynfield_offset < 0) > + return -rte_errno; > + init_once =3D true; > + } > + IP6_REWRITE_NODE_PRIV1_OFF(node->ctx) =3D node_mbuf_priv1_dynfiel= d_offset; > + > + node_dbg("ip6_rewrite", "Initialized ip6_rewrite node"); > + > + return 0; > +} > + > +int > +ip6_rewrite_set_next(uint16_t port_id, uint16_t next_index) > +{ > + if (ip6_rewrite_nm =3D=3D NULL) { > + ip6_rewrite_nm =3D rte_zmalloc( > + "ip6_rewrite", sizeof(struct ip6_rewrite_node_mai= n), > + RTE_CACHE_LINE_SIZE); > + if (ip6_rewrite_nm =3D=3D NULL) > + return -ENOMEM; > + } > + ip6_rewrite_nm->next_index[port_id] =3D next_index; > + > + return 0; > +} > + > +int > +rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, > + uint8_t rewrite_len, uint16_t dst_port) > +{ > + struct ip6_rewrite_nh_header *nh; > + > + if (next_hop >=3D RTE_GRAPH_IP6_REWRITE_MAX_NH) > + return -EINVAL; > + > + if (rewrite_len > RTE_GRAPH_IP6_REWRITE_MAX_LEN) > + return -EINVAL; > + > + if (ip6_rewrite_nm =3D=3D NULL) { > + ip6_rewrite_nm =3D rte_zmalloc( > + "ip6_rewrite", sizeof(struct ip6_rewrite_node_mai= n), > + RTE_CACHE_LINE_SIZE); > + if (ip6_rewrite_nm =3D=3D NULL) > + return -ENOMEM; > + } > + > + /* Check if dst port doesn't exist as edge */ > + if (!ip6_rewrite_nm->next_index[dst_port]) > + return -EINVAL; > + > + /* Update next hop */ > + nh =3D &ip6_rewrite_nm->nh[next_hop]; > + > + memcpy(nh->rewrite_data, rewrite_data, rewrite_len); > + nh->tx_node =3D ip6_rewrite_nm->next_index[dst_port]; > + nh->rewrite_len =3D rewrite_len; > + nh->enabled =3D true; > + > + return 0; > +} > + > +static struct rte_node_register ip6_rewrite_node =3D { > + .process =3D ip6_rewrite_node_process, > + .name =3D "ip6_rewrite", > + /* Default edge i.e '0' is pkt drop */ > + .nb_edges =3D 1, > + .next_nodes =3D { > + [0] =3D "pkt_drop", > + }, > + .init =3D ip6_rewrite_node_init, > +}; > + > +struct rte_node_register * > +ip6_rewrite_node_get(void) > +{ > + return &ip6_rewrite_node; > +} > + > +RTE_NODE_REGISTER(ip6_rewrite_node); > diff --git a/lib/node/ip6_rewrite_priv.h b/lib/node/ip6_rewrite_priv.h > new file mode 100644 > index 0000000000..93db28bec0 > --- /dev/null > +++ b/lib/node/ip6_rewrite_priv.h > @@ -0,0 +1,69 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > +#ifndef __INCLUDE_IP6_REWRITE_PRIV_H__ > +#define __INCLUDE_IP6_REWRITE_PRIV_H__ > + > +#include > + > +#define RTE_GRAPH_IP6_REWRITE_MAX_NH 64 > +#define RTE_GRAPH_IP6_REWRITE_MAX_LEN 56 > + > +/** > + * @internal > + * > + * Ipv6 rewrite next hop header data structure. Used to store port speci= fic > + * rewrite data. > + */ > +struct ip6_rewrite_nh_header { > + uint16_t rewrite_len; /**< Header rewrite length. */ > + uint16_t tx_node; /**< Tx node next index identifier. */ > + uint16_t enabled; /**< NH enable flag */ > + uint16_t rsvd; > + union { > + struct { > + struct rte_ether_addr dst; > + /**< Destination mac address. */ > + struct rte_ether_addr src; > + /**< Source mac address. */ > + }; > + uint8_t rewrite_data[RTE_GRAPH_IP6_REWRITE_MAX_LEN]; > + /**< Generic rewrite data */ > + }; > +}; > + > +/** > + * @internal > + * > + * Ipv6 node main data structure. > + */ > +struct ip6_rewrite_node_main { > + struct ip6_rewrite_nh_header nh[RTE_GRAPH_IP6_REWRITE_MAX_NH]; > + /**< Array of next hop header data */ > + uint16_t next_index[RTE_MAX_ETHPORTS]; > + /**< Next index of each configured port. */ > +}; > + > +/** > + * @internal > + * > + * Get the ipv6 rewrite node. > + * > + * @return > + * Pointer to the ipv6 rewrite node. > + */ > +struct rte_node_register *ip6_rewrite_node_get(void); > + > +/** > + * @internal > + * > + * Set the Edge index of a given port_id. > + * > + * @param port_id > + * Ethernet port identifier. > + * @param next_index > + * Edge index of the Given Tx node. > + */ > +int ip6_rewrite_set_next(uint16_t port_id, uint16_t next_index); > + > +#endif /* __INCLUDE_IP6_REWRITE_PRIV_H__ */ > diff --git a/lib/node/meson.build b/lib/node/meson.build > index cd30847a0b..b2f04269c5 100644 > --- a/lib/node/meson.build > +++ b/lib/node/meson.build > @@ -14,6 +14,7 @@ sources =3D files( > 'ip4_lookup.c', > 'ip6_lookup.c', > 'ip4_rewrite.c', > + 'ip6_rewrite.c', > 'log.c', > 'null.c', > 'pkt_cls.c', > -- > 2.25.1 >