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

Generated by: LCOV version 1.14