LCOV - code coverage report
Current view: top level - lib/node - ip4_rewrite.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 143 0.7 %
Date: 2025-05-01 17:49:45 Functions: 1 6 16.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 72 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2020 Marvell International Ltd.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <eal_export.h>
       6                 :            : #include <rte_ethdev.h>
       7                 :            : #include <rte_ether.h>
       8                 :            : #include <rte_graph.h>
       9                 :            : #include <rte_graph_worker.h>
      10                 :            : #include <rte_ip.h>
      11                 :            : #include <rte_malloc.h>
      12                 :            : #include <rte_vect.h>
      13                 :            : 
      14                 :            : #include "rte_node_ip4_api.h"
      15                 :            : 
      16                 :            : #include "ip4_rewrite_priv.h"
      17                 :            : #include "node_private.h"
      18                 :            : 
      19                 :            : struct ip4_rewrite_node_ctx {
      20                 :            :         /* Dynamic offset to mbuf priv1 */
      21                 :            :         int mbuf_priv1_off;
      22                 :            :         /* Cached next index */
      23                 :            :         uint16_t next_index;
      24                 :            : };
      25                 :            : 
      26                 :            : static struct ip4_rewrite_node_main *ip4_rewrite_nm;
      27                 :            : 
      28                 :            : #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \
      29                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->next_index)
      30                 :            : 
      31                 :            : #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \
      32                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off)
      33                 :            : 
      34                 :            : static uint16_t
      35                 :          0 : ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
      36                 :            :                          void **objs, uint16_t nb_objs)
      37                 :            : {
      38                 :            :         struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
      39                 :          0 :         struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh;
      40                 :          0 :         const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
      41                 :            :         uint16_t next0, next1, next2, next3, next_index;
      42                 :            :         struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3;
      43                 :            :         uint16_t n_left_from, held = 0, last_spec = 0;
      44                 :            :         void *d0, *d1, *d2, *d3;
      45                 :            :         void **to_next, **from;
      46                 :            :         rte_xmm_t priv01;
      47                 :            :         rte_xmm_t priv23;
      48                 :            :         int i;
      49                 :            : 
      50                 :            :         /* Speculative next as last next */
      51                 :          0 :         next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx);
      52                 :            :         rte_prefetch0(nh);
      53                 :            : 
      54                 :            :         pkts = (struct rte_mbuf **)objs;
      55                 :            :         from = objs;
      56                 :            :         n_left_from = nb_objs;
      57                 :            : 
      58   [ #  #  #  # ]:          0 :         for (i = 0; i < 4 && i < n_left_from; i++)
      59                 :          0 :                 rte_prefetch0(pkts[i]);
      60                 :            : 
      61                 :            :         /* Get stream for the speculated next node */
      62                 :          0 :         to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
      63                 :            :         /* Update Ethernet header of pkts */
      64         [ #  # ]:          0 :         while (n_left_from >= 4) {
      65         [ #  # ]:          0 :                 if (likely(n_left_from > 7)) {
      66                 :            :                         /* Prefetch only next-mbuf struct and priv area.
      67                 :            :                          * Data need not be prefetched as we only write.
      68                 :            :                          */
      69                 :          0 :                         rte_prefetch0(pkts[4]);
      70                 :          0 :                         rte_prefetch0(pkts[5]);
      71                 :          0 :                         rte_prefetch0(pkts[6]);
      72                 :          0 :                         rte_prefetch0(pkts[7]);
      73                 :            :                 }
      74                 :            : 
      75                 :          0 :                 mbuf0 = pkts[0];
      76                 :          0 :                 mbuf1 = pkts[1];
      77                 :          0 :                 mbuf2 = pkts[2];
      78                 :          0 :                 mbuf3 = pkts[3];
      79                 :            : 
      80                 :          0 :                 pkts += 4;
      81         [ #  # ]:          0 :                 n_left_from -= 4;
      82                 :          0 :                 priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u;
      83                 :          0 :                 priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u;
      84                 :          0 :                 priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u;
      85                 :          0 :                 priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u;
      86                 :            : 
      87                 :            :                 /* Increment checksum by one. */
      88                 :          0 :                 priv01.u32[1] += rte_cpu_to_be_16(0x0100);
      89                 :          0 :                 priv01.u32[3] += rte_cpu_to_be_16(0x0100);
      90                 :          0 :                 priv23.u32[1] += rte_cpu_to_be_16(0x0100);
      91                 :          0 :                 priv23.u32[3] += rte_cpu_to_be_16(0x0100);
      92                 :            : 
      93                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */
      94                 :          0 :                 d0 = rte_pktmbuf_mtod(mbuf0, void *);
      95                 :          0 :                 rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data,
      96         [ #  # ]:          0 :                            nh[priv01.u16[0]].rewrite_len);
      97                 :            : 
      98                 :          0 :                 next0 = nh[priv01.u16[0]].tx_node;
      99                 :            :                 ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
     100                 :            :                                               sizeof(struct rte_ether_hdr));
     101                 :          0 :                 ip0->time_to_live = priv01.u16[1] - 1;
     102                 :          0 :                 ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3];
     103                 :            : 
     104                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */
     105                 :          0 :                 d1 = rte_pktmbuf_mtod(mbuf1, void *);
     106                 :          0 :                 rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data,
     107         [ #  # ]:          0 :                            nh[priv01.u16[4]].rewrite_len);
     108                 :            : 
     109                 :          0 :                 next1 = nh[priv01.u16[4]].tx_node;
     110                 :            :                 ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 +
     111                 :            :                                               sizeof(struct rte_ether_hdr));
     112                 :          0 :                 ip1->time_to_live = priv01.u16[5] - 1;
     113                 :          0 :                 ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7];
     114                 :            : 
     115                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */
     116                 :          0 :                 d2 = rte_pktmbuf_mtod(mbuf2, void *);
     117                 :          0 :                 rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data,
     118         [ #  # ]:          0 :                            nh[priv23.u16[0]].rewrite_len);
     119                 :          0 :                 next2 = nh[priv23.u16[0]].tx_node;
     120                 :            :                 ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 +
     121                 :            :                                               sizeof(struct rte_ether_hdr));
     122                 :          0 :                 ip2->time_to_live = priv23.u16[1] - 1;
     123                 :          0 :                 ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3];
     124                 :            : 
     125                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */
     126                 :          0 :                 d3 = rte_pktmbuf_mtod(mbuf3, void *);
     127                 :          0 :                 rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data,
     128         [ #  # ]:          0 :                            nh[priv23.u16[4]].rewrite_len);
     129                 :            : 
     130                 :          0 :                 next3 = nh[priv23.u16[4]].tx_node;
     131                 :            :                 ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 +
     132                 :            :                                               sizeof(struct rte_ether_hdr));
     133                 :          0 :                 ip3->time_to_live = priv23.u16[5] - 1;
     134                 :          0 :                 ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7];
     135                 :            : 
     136                 :            :                 /* Enqueue four to next node */
     137                 :          0 :                 rte_edge_t fix_spec =
     138                 :          0 :                         ((next_index == next0) && (next0 == next1) &&
     139   [ #  #  #  # ]:          0 :                          (next1 == next2) && (next2 == next3));
     140                 :            : 
     141         [ #  # ]:          0 :                 if (unlikely(fix_spec == 0)) {
     142                 :            :                         /* Copy things successfully speculated till now */
     143         [ #  # ]:          0 :                         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
     144                 :          0 :                         from += last_spec;
     145                 :          0 :                         to_next += last_spec;
     146                 :          0 :                         held += last_spec;
     147                 :            :                         last_spec = 0;
     148                 :            : 
     149                 :            :                         /* next0 */
     150         [ #  # ]:          0 :                         if (next_index == next0) {
     151                 :          0 :                                 to_next[0] = from[0];
     152                 :          0 :                                 to_next++;
     153                 :          0 :                                 held++;
     154                 :            :                         } else {
     155                 :          0 :                                 rte_node_enqueue_x1(graph, node, next0,
     156                 :            :                                                     from[0]);
     157                 :            :                         }
     158                 :            : 
     159                 :            :                         /* next1 */
     160         [ #  # ]:          0 :                         if (next_index == next1) {
     161                 :          0 :                                 to_next[0] = from[1];
     162                 :          0 :                                 to_next++;
     163                 :          0 :                                 held++;
     164                 :            :                         } else {
     165                 :          0 :                                 rte_node_enqueue_x1(graph, node, next1,
     166                 :            :                                                     from[1]);
     167                 :            :                         }
     168                 :            : 
     169                 :            :                         /* next2 */
     170         [ #  # ]:          0 :                         if (next_index == next2) {
     171                 :          0 :                                 to_next[0] = from[2];
     172                 :          0 :                                 to_next++;
     173                 :          0 :                                 held++;
     174                 :            :                         } else {
     175                 :          0 :                                 rte_node_enqueue_x1(graph, node, next2,
     176                 :            :                                                     from[2]);
     177                 :            :                         }
     178                 :            : 
     179                 :            :                         /* next3 */
     180         [ #  # ]:          0 :                         if (next_index == next3) {
     181                 :          0 :                                 to_next[0] = from[3];
     182                 :          0 :                                 to_next++;
     183                 :          0 :                                 held++;
     184                 :            :                         } else {
     185                 :          0 :                                 rte_node_enqueue_x1(graph, node, next3,
     186                 :            :                                                     from[3]);
     187                 :            :                         }
     188                 :            : 
     189                 :          0 :                         from += 4;
     190                 :            : 
     191                 :            :                         /* Change speculation if last two are same */
     192         [ #  # ]:          0 :                         if ((next_index != next3) && (next2 == next3)) {
     193                 :            :                                 /* Put the current speculated node */
     194         [ #  # ]:          0 :                                 rte_node_next_stream_put(graph, node,
     195                 :            :                                                          next_index, held);
     196                 :            :                                 held = 0;
     197                 :            : 
     198                 :            :                                 /* Get next speculated stream */
     199                 :            :                                 next_index = next3;
     200                 :          0 :                                 to_next = rte_node_next_stream_get(
     201                 :            :                                         graph, node, next_index, nb_objs);
     202                 :            :                         }
     203                 :            :                 } else {
     204                 :          0 :                         last_spec += 4;
     205                 :            :                 }
     206                 :            :         }
     207                 :            : 
     208         [ #  # ]:          0 :         while (n_left_from > 0) {
     209                 :            :                 uint16_t chksum;
     210                 :            : 
     211                 :          0 :                 mbuf0 = pkts[0];
     212                 :            : 
     213                 :          0 :                 pkts += 1;
     214                 :          0 :                 n_left_from -= 1;
     215                 :            : 
     216         [ #  # ]:          0 :                 d0 = rte_pktmbuf_mtod(mbuf0, void *);
     217                 :          0 :                 rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data,
     218         [ #  # ]:          0 :                            nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len);
     219                 :            : 
     220                 :          0 :                 next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node;
     221                 :            :                 ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
     222                 :            :                                               sizeof(struct rte_ether_hdr));
     223                 :          0 :                 chksum = node_mbuf_priv1(mbuf0, dyn)->cksum +
     224                 :            :                          rte_cpu_to_be_16(0x0100);
     225                 :          0 :                 chksum += chksum >= 0xffff;
     226                 :          0 :                 ip0->hdr_checksum = chksum;
     227                 :          0 :                 ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1;
     228                 :            : 
     229         [ #  # ]:          0 :                 if (unlikely(next_index ^ next0)) {
     230                 :            :                         /* Copy things successfully speculated till now */
     231         [ #  # ]:          0 :                         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
     232                 :          0 :                         from += last_spec;
     233                 :          0 :                         to_next += last_spec;
     234                 :          0 :                         held += last_spec;
     235                 :            :                         last_spec = 0;
     236                 :            : 
     237                 :          0 :                         rte_node_enqueue_x1(graph, node, next0, from[0]);
     238                 :          0 :                         from += 1;
     239                 :            :                 } else {
     240                 :          0 :                         last_spec += 1;
     241                 :            :                 }
     242                 :            :         }
     243                 :            : 
     244                 :            :         /* !!! Home run !!! */
     245         [ #  # ]:          0 :         if (likely(last_spec == nb_objs)) {
     246                 :          0 :                 rte_node_next_stream_move(graph, node, next_index);
     247                 :          0 :                 return nb_objs;
     248                 :            :         }
     249                 :            : 
     250                 :          0 :         held += last_spec;
     251         [ #  # ]:          0 :         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
     252         [ #  # ]:          0 :         rte_node_next_stream_put(graph, node, next_index, held);
     253                 :            :         /* Save the last next used */
     254                 :          0 :         IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index;
     255                 :            : 
     256                 :          0 :         return nb_objs;
     257                 :            : }
     258                 :            : 
     259                 :            : static int
     260                 :          0 : ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
     261                 :            : {
     262                 :            :         static bool init_once;
     263                 :            : 
     264                 :            :         RTE_SET_USED(graph);
     265                 :            :         RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ);
     266                 :            : 
     267         [ #  # ]:          0 :         if (!init_once) {
     268                 :          0 :                 node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register(
     269                 :            :                                 &node_mbuf_priv1_dynfield_desc);
     270         [ #  # ]:          0 :                 if (node_mbuf_priv1_dynfield_offset < 0)
     271                 :          0 :                         return -rte_errno;
     272                 :          0 :                 init_once = true;
     273                 :            :         }
     274                 :          0 :         IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset;
     275                 :            : 
     276                 :          0 :         node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized");
     277                 :            : 
     278                 :          0 :         return 0;
     279                 :            : }
     280                 :            : 
     281                 :            : int
     282                 :          0 : ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
     283                 :            : {
     284         [ #  # ]:          0 :         if (ip4_rewrite_nm == NULL) {
     285                 :          0 :                 ip4_rewrite_nm = rte_zmalloc(
     286                 :            :                         "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
     287                 :            :                         RTE_CACHE_LINE_SIZE);
     288         [ #  # ]:          0 :                 if (ip4_rewrite_nm == NULL)
     289                 :            :                         return -ENOMEM;
     290                 :            :         }
     291                 :          0 :         ip4_rewrite_nm->next_index[port_id] = next_index;
     292                 :            : 
     293                 :          0 :         return 0;
     294                 :            : }
     295                 :            : 
     296                 :            : RTE_EXPORT_SYMBOL(rte_node_ip4_rewrite_add)
     297                 :            : int
     298                 :          0 : rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data,
     299                 :            :                          uint8_t rewrite_len, uint16_t dst_port)
     300                 :            : {
     301                 :            :         struct ip4_rewrite_nh_header *nh;
     302                 :            : 
     303         [ #  # ]:          0 :         if (next_hop >= RTE_GRAPH_IP4_REWRITE_MAX_NH)
     304                 :            :                 return -EINVAL;
     305                 :            : 
     306         [ #  # ]:          0 :         if (rewrite_len > RTE_GRAPH_IP4_REWRITE_MAX_LEN)
     307                 :            :                 return -EINVAL;
     308                 :            : 
     309         [ #  # ]:          0 :         if (ip4_rewrite_nm == NULL) {
     310                 :          0 :                 ip4_rewrite_nm = rte_zmalloc(
     311                 :            :                         "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
     312                 :            :                         RTE_CACHE_LINE_SIZE);
     313         [ #  # ]:          0 :                 if (ip4_rewrite_nm == NULL)
     314                 :            :                         return -ENOMEM;
     315                 :            :         }
     316                 :            : 
     317                 :            :         /* Check if dst port doesn't exist as edge */
     318         [ #  # ]:          0 :         if (!ip4_rewrite_nm->next_index[dst_port])
     319                 :            :                 return -EINVAL;
     320                 :            : 
     321                 :            :         /* Update next hop */
     322                 :          0 :         nh = &ip4_rewrite_nm->nh[next_hop];
     323                 :            : 
     324                 :          0 :         memcpy(nh->rewrite_data, rewrite_data, rewrite_len);
     325                 :          0 :         nh->tx_node = ip4_rewrite_nm->next_index[dst_port];
     326                 :          0 :         nh->rewrite_len = rewrite_len;
     327                 :          0 :         nh->enabled = true;
     328                 :            : 
     329                 :          0 :         return 0;
     330                 :            : }
     331                 :            : 
     332                 :            : static struct rte_node_register ip4_rewrite_node = {
     333                 :            :         .process = ip4_rewrite_node_process,
     334                 :            :         .name = "ip4_rewrite",
     335                 :            :         /* Default edge i.e '0' is pkt drop */
     336                 :            :         .nb_edges = 1,
     337                 :            :         .next_nodes = {
     338                 :            :                 [0] = "pkt_drop",
     339                 :            :         },
     340                 :            :         .init = ip4_rewrite_node_init,
     341                 :            : };
     342                 :            : 
     343                 :            : struct rte_node_register *
     344                 :          0 : ip4_rewrite_node_get(void)
     345                 :            : {
     346                 :          0 :         return &ip4_rewrite_node;
     347                 :            : }
     348                 :            : 
     349                 :        252 : RTE_NODE_REGISTER(ip4_rewrite_node);

Generated by: LCOV version 1.14