LCOV - code coverage report
Current view: top level - lib/node - ip4_rewrite.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 205 1.0 %
Date: 2025-08-01 17:49:26 Functions: 2 8 25.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 238 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2020 Marvell International Ltd.
       3                 :            :  */
       4                 :            : #include <eal_export.h>
       5                 :            : #include <rte_ethdev.h>
       6                 :            : #include <rte_ether.h>
       7                 :            : #include <rte_graph.h>
       8                 :            : #include <rte_graph_worker.h>
       9                 :            : #include <rte_graph_feature_arc_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                 :            : #include "interface_tx_feature_priv.h"
      19                 :            : 
      20                 :            : #ifndef RTE_IP4_OUTPUT_ARC_INDEXES
      21                 :            : #define RTE_IP4_OUTPUT_ARC_INDEXES RTE_MAX_ETHPORTS
      22                 :            : #endif
      23                 :            : 
      24                 :            : struct ip4_rewrite_node_ctx {
      25                 :            :         /* Dynamic offset to mbuf priv1 */
      26                 :            :         int mbuf_priv1_off;
      27                 :            :         /* Dynamic offset to feature arc field */
      28                 :            :         int arc_dyn_off;
      29                 :            :         /* Cached next index */
      30                 :            :         uint16_t next_index;
      31                 :            :         /* tx interface of last mbuf */
      32                 :            :         uint16_t last_tx_if;
      33                 :            :         /* Cached feature arc handle */
      34                 :            :         rte_graph_feature_arc_t output_feature_arc;
      35                 :            : };
      36                 :            : 
      37                 :            : static struct ip4_rewrite_node_main *ip4_rewrite_nm;
      38                 :            : static int port_to_next_index_diff = -1;
      39                 :            : 
      40                 :            : #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \
      41                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->next_index)
      42                 :            : 
      43                 :            : #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \
      44                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off)
      45                 :            : 
      46                 :            : #define IP4_REWRITE_NODE_FEAT_OFF(ctx) \
      47                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->arc_dyn_off)
      48                 :            : 
      49                 :            : #define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \
      50                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc)
      51                 :            : 
      52                 :            : #define IP4_REWRITE_NODE_LAST_TX_IF(ctx) \
      53                 :            :         (((struct ip4_rewrite_node_ctx *)ctx)->last_tx_if)
      54                 :            : 
      55                 :            : static __rte_always_inline void
      56                 :            : check_output_feature_arc_x1(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
      57                 :            :                             struct rte_mbuf *mbuf0, uint16_t *next0,
      58                 :            :                             uint16_t *last_next_index,
      59                 :            :                             rte_graph_feature_data_t *feature_data, const int feat_dyn)
      60                 :            : {
      61                 :            :         struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL;
      62                 :            :         uint16_t port0;
      63                 :            : 
      64                 :            :         /* make sure packets are not being sent to pkt_drop node */
      65                 :          0 :         if (likely(*next0 >= port_to_next_index_diff)) {
      66                 :            : 
      67         [ #  # ]:          0 :                 port0 = (*next0) - port_to_next_index_diff;
      68                 :            : 
      69                 :            :                 /* get pointer to feature arc mbuf */
      70                 :            :                 d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, feat_dyn);
      71                 :            : 
      72                 :            :                 /* Check if last packet's tx port not same as current */
      73         [ #  # ]:          0 :                 if (*tx_if != port0) {
      74                 :            :                         if (rte_graph_feature_data_first_feature_get(arc, port0,
      75                 :            :                                                                      &d0->feature_data,
      76                 :            :                                                                      next0)) {
      77                 :          0 :                                 mbuf0->port = port0;
      78                 :            :                                 *last_next_index = *next0;
      79                 :            :                         }
      80                 :            :                         *tx_if = port0;
      81                 :          0 :                         *feature_data = d0->feature_data;
      82                 :            :                 } else {
      83         [ #  # ]:          0 :                         if (rte_graph_feature_data_is_valid(*feature_data)) {
      84                 :            :                                 *next0 = *last_next_index;
      85                 :          0 :                                 mbuf0->port = port0;
      86                 :          0 :                                 d0->feature_data = *feature_data;
      87                 :            :                         }
      88                 :            :                 }
      89                 :            :         }
      90                 :            : }
      91                 :            : 
      92                 :            : static __rte_always_inline void
      93                 :            : check_output_feature_arc_x4(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
      94                 :            :                             struct rte_mbuf *mbuf0, struct rte_mbuf *mbuf1,
      95                 :            :                             struct rte_mbuf *mbuf2, struct rte_mbuf *mbuf3,
      96                 :            :                             uint16_t *next0, uint16_t *next1, uint16_t *next2,
      97                 :            :                             uint16_t *next3, uint16_t *last_next_index,
      98                 :            :                             rte_graph_feature_data_t *feature_data, const int feat_dyn)
      99                 :            : {
     100                 :            :         struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL, *d1 = NULL, *d2 = NULL, *d3 = NULL;
     101                 :            :         uint16_t port0, port1, port2, port3;
     102                 :            :         uint16_t xor = 0;
     103                 :            : 
     104                 :            :         /* get pointer to feature arc dyn field */
     105                 :            :         d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, feat_dyn);
     106                 :            :         d1 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf1, feat_dyn);
     107                 :            :         d2 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf2, feat_dyn);
     108                 :            :         d3 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf3, feat_dyn);
     109                 :            : 
     110                 :            :         /*
     111                 :            :          * Check if all four packets are going to same next_index/port
     112                 :            :          */
     113                 :          0 :         xor = (*tx_if + port_to_next_index_diff) ^ (*next0);
     114                 :          0 :         xor += (*next0) ^ (*next1);
     115                 :          0 :         xor += (*next1) ^ (*next2);
     116                 :          0 :         xor += (*next2) ^ (*next3);
     117                 :            : 
     118         [ #  # ]:          0 :         if (xor) {
     119                 :            :                 /* packets tx ports are not same, check first feature for each mbuf
     120                 :            :                  * make sure next0 != 0 which is pkt_drop
     121                 :            :                  */
     122                 :          0 :                 port0 = (*next0) - port_to_next_index_diff;
     123                 :          0 :                 port1 = (*next1) - port_to_next_index_diff;
     124                 :          0 :                 port2 = (*next2) - port_to_next_index_diff;
     125                 :          0 :                 port3 = (*next3) - port_to_next_index_diff;
     126   [ #  #  #  # ]:          0 :                 if (unlikely((*next0 >= port_to_next_index_diff) &&
     127                 :            :                              rte_graph_feature_data_first_feature_get(arc, port0,
     128                 :            :                                                                       &d0->feature_data,
     129                 :            :                                                                       next0))) {
     130                 :            :                         /* update next0 from feature arc */
     131                 :          0 :                         mbuf0->port = port0;
     132                 :            :                 }
     133                 :            : 
     134   [ #  #  #  # ]:          0 :                 if (unlikely((*next1 >= port_to_next_index_diff) &&
     135                 :            :                              rte_graph_feature_data_first_feature_get(arc, port1,
     136                 :            :                                                                       &d1->feature_data,
     137                 :            :                                                                       next1))) {
     138                 :          0 :                         mbuf1->port = port1;
     139                 :            :                 }
     140                 :            : 
     141   [ #  #  #  # ]:          0 :                 if (unlikely((*next2 >= port_to_next_index_diff) &&
     142                 :            :                              rte_graph_feature_data_first_feature_get(arc, port2,
     143                 :            :                                                                       &d2->feature_data,
     144                 :            :                                                                       next2))) {
     145                 :          0 :                         mbuf2->port = port2;
     146                 :            :                 }
     147                 :            : 
     148   [ #  #  #  # ]:          0 :                 if (unlikely((*next3 >= port_to_next_index_diff) &&
     149                 :            :                              rte_graph_feature_data_first_feature_get(arc, port3,
     150                 :            :                                                                       &d3->feature_data,
     151                 :            :                                                                       next3))) {
     152                 :          0 :                         mbuf3->port = port3;
     153                 :            : 
     154                 :            :                         *tx_if = port3;
     155                 :            :                         *last_next_index = *next3;
     156                 :            :                 }
     157                 :          0 :                 *feature_data = d3->feature_data;
     158                 :            :         } else {
     159                 :            :                 /* All packets are same as last tx port. Check if feature enabled
     160                 :            :                  * on last packet is valid or not. If invalid no need to
     161                 :            :                  * change any next[0-3]
     162                 :            :                  * Also check packet is not being sent to pkt_drop node
     163                 :            :                  */
     164   [ #  #  #  # ]:          0 :                 if (unlikely(rte_graph_feature_data_is_valid(*feature_data) &&
     165                 :            :                              (*next0 != 0))) {
     166                 :            :                         *next0 = *last_next_index;
     167                 :            :                         *next1 = *last_next_index;
     168                 :            :                         *next2 = *last_next_index;
     169                 :            :                         *next3 = *last_next_index;
     170                 :            : 
     171                 :          0 :                         d0->feature_data = *feature_data;
     172                 :          0 :                         d1->feature_data = *feature_data;
     173                 :          0 :                         d2->feature_data = *feature_data;
     174                 :          0 :                         d3->feature_data = *feature_data;
     175                 :            : 
     176                 :          0 :                         mbuf0->port = *tx_if;
     177                 :          0 :                         mbuf1->port = *tx_if;
     178                 :          0 :                         mbuf2->port = *tx_if;
     179                 :          0 :                         mbuf3->port = *tx_if;
     180                 :            :                 }
     181                 :            :         }
     182                 :            : }
     183                 :            : 
     184                 :            : static __rte_always_inline uint16_t
     185                 :            : __ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
     186                 :            :                            void **objs, uint16_t nb_objs,
     187                 :            :                            const int dyn, const int feat_dyn, const int check_enabled_features,
     188                 :            :                            struct rte_graph_feature_arc *out_feature_arc)
     189                 :            : {
     190                 :            :         rte_graph_feature_data_t feature_data = RTE_GRAPH_FEATURE_DATA_INVALID;
     191                 :            :         struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
     192                 :          0 :         struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh;
     193                 :            :         uint16_t next0, next1, next2, next3, next_index;
     194                 :            :         struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3;
     195                 :            :         uint16_t n_left_from, held = 0, last_spec = 0;
     196                 :            :         uint16_t last_tx_if, last_next_index;
     197                 :            :         void *d0, *d1, *d2, *d3;
     198                 :            :         void **to_next, **from;
     199                 :            :         rte_xmm_t priv01;
     200                 :            :         rte_xmm_t priv23;
     201                 :            :         int i;
     202                 :            : 
     203                 :            :         /* Speculative next as last next */
     204                 :          0 :         next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx);
     205                 :          0 :         rte_prefetch0(nh);
     206                 :            : 
     207                 :            :         pkts = (struct rte_mbuf **)objs;
     208                 :            :         from = objs;
     209                 :            :         n_left_from = nb_objs;
     210                 :            : 
     211   [ #  #  #  #  :          0 :         for (i = 0; i < 4 && i < n_left_from; i++)
          #  #  #  #  #  
                #  #  # ]
     212                 :          0 :                 rte_prefetch0(pkts[i]);
     213                 :            : 
     214                 :            :         if (check_enabled_features) {
     215                 :            :                 rte_graph_feature_arc_prefetch(out_feature_arc);
     216                 :            : 
     217         [ #  # ]:          0 :                 last_tx_if = IP4_REWRITE_NODE_LAST_TX_IF(node->ctx);
     218                 :            : 
     219                 :            :                 /* If feature is enabled on last_tx_if, prefetch data
     220                 :            :                  * corresponding to first feature
     221                 :            :                  */
     222         [ #  # ]:          0 :                 if (unlikely(rte_graph_feature_data_first_feature_get(out_feature_arc,
     223                 :            :                                                                       last_tx_if,
     224                 :            :                                                                       &feature_data,
     225                 :            :                                                                       &last_next_index)))
     226                 :            :                         rte_graph_feature_arc_feature_data_prefetch(out_feature_arc,
     227                 :            :                                                                     feature_data);
     228                 :            : 
     229                 :            :                 /* Reset last_tx_if and last_next_index to call feature arc APIs
     230                 :            :                  * for initial packets in every node loop
     231                 :            :                  */
     232                 :            :                 last_tx_if = UINT16_MAX;
     233                 :            :                 last_next_index = UINT16_MAX;
     234                 :            :         }
     235                 :            : 
     236                 :            :         /* Get stream for the speculated next node */
     237                 :          0 :         to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
     238                 :            :         /* Update Ethernet header of pkts */
     239   [ #  #  #  #  :          0 :         while (n_left_from >= 4) {
                   #  # ]
     240   [ #  #  #  #  :          0 :                 if (likely(n_left_from > 7)) {
                   #  # ]
     241                 :            :                         /* Prefetch only next-mbuf struct and priv area.
     242                 :            :                          * Data need not be prefetched as we only write.
     243                 :            :                          */
     244                 :          0 :                         rte_prefetch0(pkts[4]);
     245                 :          0 :                         rte_prefetch0(pkts[5]);
     246                 :          0 :                         rte_prefetch0(pkts[6]);
     247                 :          0 :                         rte_prefetch0(pkts[7]);
     248                 :            :                 }
     249                 :            : 
     250                 :          0 :                 mbuf0 = pkts[0];
     251                 :          0 :                 mbuf1 = pkts[1];
     252                 :          0 :                 mbuf2 = pkts[2];
     253                 :          0 :                 mbuf3 = pkts[3];
     254                 :            : 
     255                 :          0 :                 pkts += 4;
     256   [ #  #  #  #  :          0 :                 n_left_from -= 4;
                   #  # ]
     257                 :            : 
     258                 :          0 :                 priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u;
     259                 :          0 :                 priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u;
     260                 :          0 :                 priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u;
     261                 :          0 :                 priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u;
     262                 :            : 
     263                 :            :                 /* Increment checksum by one. */
     264                 :          0 :                 priv01.u32[1] += rte_cpu_to_be_16(0x0100);
     265                 :          0 :                 priv01.u32[3] += rte_cpu_to_be_16(0x0100);
     266                 :          0 :                 priv23.u32[1] += rte_cpu_to_be_16(0x0100);
     267                 :          0 :                 priv23.u32[3] += rte_cpu_to_be_16(0x0100);
     268                 :            : 
     269                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */
     270                 :          0 :                 d0 = rte_pktmbuf_mtod(mbuf0, void *);
     271                 :          0 :                 rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data,
     272   [ #  #  #  #  :          0 :                            nh[priv01.u16[0]].rewrite_len);
                   #  # ]
     273                 :            : 
     274                 :          0 :                 next0 = nh[priv01.u16[0]].tx_node;
     275                 :            :                 ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
     276                 :            :                                               sizeof(struct rte_ether_hdr));
     277                 :          0 :                 ip0->time_to_live = priv01.u16[1] - 1;
     278                 :          0 :                 ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3];
     279                 :            : 
     280                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */
     281                 :          0 :                 d1 = rte_pktmbuf_mtod(mbuf1, void *);
     282                 :          0 :                 rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data,
     283   [ #  #  #  #  :          0 :                            nh[priv01.u16[4]].rewrite_len);
                   #  # ]
     284                 :            : 
     285                 :          0 :                 next1 = nh[priv01.u16[4]].tx_node;
     286                 :            :                 ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 +
     287                 :            :                                               sizeof(struct rte_ether_hdr));
     288                 :          0 :                 ip1->time_to_live = priv01.u16[5] - 1;
     289                 :          0 :                 ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7];
     290                 :            : 
     291                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */
     292                 :          0 :                 d2 = rte_pktmbuf_mtod(mbuf2, void *);
     293                 :          0 :                 rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data,
     294   [ #  #  #  #  :          0 :                            nh[priv23.u16[0]].rewrite_len);
                   #  # ]
     295                 :          0 :                 next2 = nh[priv23.u16[0]].tx_node;
     296                 :            :                 ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 +
     297                 :            :                                               sizeof(struct rte_ether_hdr));
     298                 :          0 :                 ip2->time_to_live = priv23.u16[1] - 1;
     299                 :          0 :                 ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3];
     300                 :            : 
     301                 :            :                 /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */
     302                 :          0 :                 d3 = rte_pktmbuf_mtod(mbuf3, void *);
     303                 :          0 :                 rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data,
     304   [ #  #  #  #  :          0 :                            nh[priv23.u16[4]].rewrite_len);
                   #  # ]
     305                 :            : 
     306                 :          0 :                 next3 = nh[priv23.u16[4]].tx_node;
     307                 :            :                 ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 +
     308                 :            :                                               sizeof(struct rte_ether_hdr));
     309                 :          0 :                 ip3->time_to_live = priv23.u16[5] - 1;
     310   [ #  #  #  # ]:          0 :                 ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7];
     311                 :            : 
     312                 :            :                 /* Once all mbufs are updated with next hop data.
     313                 :            :                  * check if any feature is enabled to override
     314                 :            :                  * next edges
     315                 :            :                  */
     316                 :            :                 if (check_enabled_features)
     317                 :            :                         check_output_feature_arc_x4(out_feature_arc, &last_tx_if,
     318                 :            :                                                     mbuf0, mbuf1, mbuf2, mbuf3,
     319                 :            :                                                     &next0, &next1, &next2, &next3,
     320                 :            :                                                     &last_next_index, &feature_data, feat_dyn);
     321                 :            : 
     322                 :            :                 /* Enqueue four to next node */
     323                 :          0 :                 rte_edge_t fix_spec =
     324   [ #  #  #  #  :          0 :                         ((next_index == next0) && (next0 == next1) &&
          #  #  #  #  #  
                #  #  # ]
     325   [ #  #  #  #  :          0 :                          (next1 == next2) && (next2 == next3));
          #  #  #  #  #  
                #  #  # ]
     326                 :            : 
     327   [ #  #  #  #  :          0 :                 if (unlikely(fix_spec == 0)) {
                   #  # ]
     328                 :            :                         /* Copy things successfully speculated till now */
     329   [ #  #  #  #  :          0 :                         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
                   #  # ]
     330                 :          0 :                         from += last_spec;
     331                 :          0 :                         to_next += last_spec;
     332                 :          0 :                         held += last_spec;
     333                 :            :                         last_spec = 0;
     334                 :            : 
     335                 :            :                         /* next0 */
     336   [ #  #  #  #  :          0 :                         if (next_index == next0) {
                   #  # ]
     337                 :          0 :                                 to_next[0] = from[0];
     338                 :          0 :                                 to_next++;
     339                 :          0 :                                 held++;
     340                 :            :                         } else {
     341                 :          0 :                                 rte_node_enqueue_x1(graph, node, next0,
     342                 :            :                                                     from[0]);
     343                 :            :                         }
     344                 :            : 
     345                 :            :                         /* next1 */
     346   [ #  #  #  #  :          0 :                         if (next_index == next1) {
                   #  # ]
     347                 :          0 :                                 to_next[0] = from[1];
     348                 :          0 :                                 to_next++;
     349                 :          0 :                                 held++;
     350                 :            :                         } else {
     351                 :          0 :                                 rte_node_enqueue_x1(graph, node, next1,
     352                 :            :                                                     from[1]);
     353                 :            :                         }
     354                 :            : 
     355                 :            :                         /* next2 */
     356   [ #  #  #  #  :          0 :                         if (next_index == next2) {
                   #  # ]
     357                 :          0 :                                 to_next[0] = from[2];
     358                 :          0 :                                 to_next++;
     359                 :          0 :                                 held++;
     360                 :            :                         } else {
     361                 :          0 :                                 rte_node_enqueue_x1(graph, node, next2,
     362                 :            :                                                     from[2]);
     363                 :            :                         }
     364                 :            : 
     365                 :            :                         /* next3 */
     366   [ #  #  #  #  :          0 :                         if (next_index == next3) {
                   #  # ]
     367                 :          0 :                                 to_next[0] = from[3];
     368                 :          0 :                                 to_next++;
     369                 :          0 :                                 held++;
     370                 :            :                         } else {
     371                 :          0 :                                 rte_node_enqueue_x1(graph, node, next3,
     372                 :            :                                                     from[3]);
     373                 :            :                         }
     374                 :            : 
     375                 :          0 :                         from += 4;
     376                 :            : 
     377                 :            :                         /* Change speculation if last two are same */
     378   [ #  #  #  #  :          0 :                         if ((next_index != next3) && (next2 == next3)) {
          #  #  #  #  #  
                #  #  # ]
     379                 :            :                                 /* Put the current speculated node */
     380                 :          0 :                                 rte_node_next_stream_put(graph, node,
     381                 :            :                                                          next_index, held);
     382                 :            :                                 held = 0;
     383                 :            : 
     384                 :            :                                 /* Get next speculated stream */
     385                 :            :                                 next_index = next3;
     386                 :          0 :                                 to_next = rte_node_next_stream_get(
     387                 :            :                                         graph, node, next_index, nb_objs);
     388                 :            :                         }
     389                 :            :                 } else {
     390                 :          0 :                         last_spec += 4;
     391                 :            :                 }
     392                 :            :         }
     393                 :            : 
     394   [ #  #  #  #  :          0 :         while (n_left_from > 0) {
                   #  # ]
     395                 :            :                 uint16_t chksum;
     396                 :            : 
     397                 :          0 :                 mbuf0 = pkts[0];
     398                 :            : 
     399                 :          0 :                 pkts += 1;
     400                 :          0 :                 n_left_from -= 1;
     401                 :            : 
     402   [ #  #  #  #  :          0 :                 d0 = rte_pktmbuf_mtod(mbuf0, void *);
                   #  # ]
     403                 :          0 :                 rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data,
     404   [ #  #  #  #  :          0 :                            nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len);
                   #  # ]
     405                 :            : 
     406                 :          0 :                 next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node;
     407                 :            :                 ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
     408                 :            :                                               sizeof(struct rte_ether_hdr));
     409                 :          0 :                 chksum = node_mbuf_priv1(mbuf0, dyn)->cksum +
     410                 :          0 :                          rte_cpu_to_be_16(0x0100);
     411                 :          0 :                 chksum += chksum >= 0xffff;
     412                 :          0 :                 ip0->hdr_checksum = chksum;
     413         [ #  # ]:          0 :                 ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1;
     414                 :            : 
     415                 :            :                 if (check_enabled_features)
     416                 :            :                         check_output_feature_arc_x1(out_feature_arc, &last_tx_if,
     417                 :            :                                                     mbuf0, &next0, &last_next_index,
     418                 :            :                                                     &feature_data, feat_dyn);
     419                 :            : 
     420   [ #  #  #  #  :          0 :                 if (unlikely(next_index ^ next0)) {
                   #  # ]
     421                 :            :                         /* Copy things successfully speculated till now */
     422   [ #  #  #  #  :          0 :                         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
                   #  # ]
     423                 :          0 :                         from += last_spec;
     424                 :          0 :                         to_next += last_spec;
     425                 :          0 :                         held += last_spec;
     426                 :            :                         last_spec = 0;
     427                 :            : 
     428                 :          0 :                         rte_node_enqueue_x1(graph, node, next0, from[0]);
     429                 :          0 :                         from += 1;
     430                 :            :                 } else {
     431                 :          0 :                         last_spec += 1;
     432                 :            :                 }
     433                 :            :         }
     434                 :            : 
     435                 :            :         /* !!! Home run !!! */
     436   [ #  #  #  #  :          0 :         if (likely(last_spec == nb_objs)) {
                   #  # ]
     437                 :          0 :                 rte_node_next_stream_move(graph, node, next_index);
     438                 :          0 :                 return nb_objs;
     439                 :            :         }
     440                 :            : 
     441                 :          0 :         held += last_spec;
     442   [ #  #  #  #  :          0 :         rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
                   #  # ]
     443                 :          0 :         rte_node_next_stream_put(graph, node, next_index, held);
     444                 :            :         /* Save the last next used */
     445                 :          0 :         IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index;
     446                 :            : 
     447                 :            :         if (check_enabled_features)
     448                 :          0 :                 IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = last_tx_if;
     449                 :            : 
     450                 :            :         return nb_objs;
     451                 :            : }
     452                 :            : 
     453                 :            : static uint16_t
     454                 :          0 : ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node,
     455                 :            :                                  void **objs, uint16_t nb_objs)
     456                 :            : {
     457                 :          0 :         const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
     458                 :          0 :         const int feat_dyn = IP4_REWRITE_NODE_FEAT_OFF(node->ctx);
     459                 :            :         struct rte_graph_feature_arc *arc = NULL;
     460                 :            : 
     461         [ #  # ]:          0 :         arc = rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx));
     462   [ #  #  #  # ]:          0 :         if (unlikely(rte_graph_feature_arc_is_any_feature_enabled(arc) &&
     463                 :            :                      (port_to_next_index_diff > 0)))
     464                 :          0 :                 return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, feat_dyn,
     465                 :            :                                                   1 /* check features */, arc);
     466                 :            : 
     467                 :          0 :         return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, 0,
     468                 :            :                                           0/* don't check features*/,
     469                 :            :                                           arc /* don't care*/);
     470                 :            : }
     471                 :            : 
     472                 :            : static uint16_t
     473                 :          0 : ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
     474                 :            :                          void **objs, uint16_t nb_objs)
     475                 :            : {
     476                 :          0 :         const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
     477                 :            : 
     478                 :          0 :         return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, 0,
     479                 :            :                                           0/* don't check features*/,
     480                 :            :                                           NULL/* don't care */);
     481                 :            : }
     482                 :            : 
     483                 :            : 
     484                 :            : static int
     485                 :          0 : ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
     486                 :            : {
     487                 :          0 :         rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER;
     488                 :            :         static bool init_once;
     489                 :            :         int dyn;
     490                 :            : 
     491                 :            :         RTE_SET_USED(graph);
     492                 :            :         RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ);
     493                 :            : 
     494                 :          0 :         dyn = rte_node_mbuf_dynfield_register();
     495         [ #  # ]:          0 :         if (dyn < 0) {
     496                 :          0 :                 node_err("ip4_rewrite", "Failed to register mbuf dynfield");
     497                 :          0 :                 return -rte_errno;
     498                 :            :         }
     499                 :            : 
     500         [ #  # ]:          0 :         if (!init_once) {
     501                 :            :                 /* Create ipv4-output feature arc, if not created
     502                 :            :                  */
     503         [ #  # ]:          0 :                 if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
     504                 :            :                                                      &feature_arc) < 0) {
     505                 :          0 :                         node_err("ip4_rewrite", "Feature arc \"%s\" not found",
     506                 :            :                                  RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
     507                 :            :                 } else {
     508                 :          0 :                         node_err("ip4_rewrite", "Feature arc \"%s\" found",
     509                 :            :                                  RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
     510                 :            :                 }
     511                 :            : 
     512                 :          0 :                 IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc;
     513                 :            : 
     514   [ #  #  #  # ]:          0 :                 if (rte_graph_feature_arc_get(feature_arc))
     515                 :          0 :                         IP4_REWRITE_NODE_FEAT_OFF(node->ctx) =
     516                 :          0 :                                 rte_graph_feature_arc_get(feature_arc)->mbuf_dyn_offset;
     517                 :            : 
     518                 :            :                 /* By default, set cached next node to pkt_drop */
     519                 :          0 :                 IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = 0;
     520                 :          0 :                 IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = 0;
     521                 :            : 
     522                 :          0 :                 init_once = true;
     523                 :            :         }
     524                 :          0 :         IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = dyn;
     525                 :          0 :         node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized");
     526                 :            : 
     527                 :          0 :         return 0;
     528                 :            : }
     529                 :            : 
     530                 :            : int
     531                 :          0 : ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
     532                 :            : {
     533                 :            :         static int once;
     534                 :            : 
     535         [ #  # ]:          0 :         if (ip4_rewrite_nm == NULL) {
     536                 :          0 :                 ip4_rewrite_nm = rte_zmalloc(
     537                 :            :                         "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
     538                 :            :                         RTE_CACHE_LINE_SIZE);
     539         [ #  # ]:          0 :                 if (ip4_rewrite_nm == NULL)
     540                 :            :                         return -ENOMEM;
     541                 :            :         }
     542         [ #  # ]:          0 :         if (!once) {
     543                 :          0 :                 port_to_next_index_diff = next_index - port_id;
     544                 :          0 :                 once = 1;
     545                 :            :         }
     546                 :          0 :         ip4_rewrite_nm->next_index[port_id] = next_index;
     547                 :            : 
     548                 :          0 :         return 0;
     549                 :            : }
     550                 :            : 
     551                 :            : RTE_EXPORT_SYMBOL(rte_node_ip4_rewrite_add)
     552                 :            : int
     553                 :          0 : rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data,
     554                 :            :                          uint8_t rewrite_len, uint16_t dst_port)
     555                 :            : {
     556                 :            :         struct ip4_rewrite_nh_header *nh;
     557                 :            : 
     558         [ #  # ]:          0 :         if (next_hop >= RTE_GRAPH_IP4_REWRITE_MAX_NH)
     559                 :            :                 return -EINVAL;
     560                 :            : 
     561         [ #  # ]:          0 :         if (rewrite_len > RTE_GRAPH_IP4_REWRITE_MAX_LEN)
     562                 :            :                 return -EINVAL;
     563                 :            : 
     564         [ #  # ]:          0 :         if (ip4_rewrite_nm == NULL) {
     565                 :          0 :                 ip4_rewrite_nm = rte_zmalloc(
     566                 :            :                         "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
     567                 :            :                         RTE_CACHE_LINE_SIZE);
     568         [ #  # ]:          0 :                 if (ip4_rewrite_nm == NULL)
     569                 :            :                         return -ENOMEM;
     570                 :            :         }
     571                 :            : 
     572                 :            :         /* Check if dst port doesn't exist as edge */
     573         [ #  # ]:          0 :         if (!ip4_rewrite_nm->next_index[dst_port])
     574                 :            :                 return -EINVAL;
     575                 :            : 
     576                 :            :         /* Update next hop */
     577                 :          0 :         nh = &ip4_rewrite_nm->nh[next_hop];
     578                 :            : 
     579                 :          0 :         memcpy(nh->rewrite_data, rewrite_data, rewrite_len);
     580                 :          0 :         nh->tx_node = ip4_rewrite_nm->next_index[dst_port];
     581                 :          0 :         nh->rewrite_len = rewrite_len;
     582                 :          0 :         nh->enabled = true;
     583                 :            : 
     584                 :          0 :         return 0;
     585                 :            : }
     586                 :            : 
     587                 :            : static struct rte_node_register ip4_rewrite_node = {
     588                 :            :         .process = ip4_rewrite_node_process,
     589                 :            :         .name = "ip4_rewrite",
     590                 :            :         /* Default edge i.e '0' is pkt drop */
     591                 :            :         .nb_edges = 1,
     592                 :            :         .next_nodes = {
     593                 :            :                 [0] = "pkt_drop",
     594                 :            :         },
     595                 :            :         .init = ip4_rewrite_node_init,
     596                 :            : };
     597                 :            : 
     598                 :            : struct rte_node_register *
     599                 :          0 : ip4_rewrite_node_get(void)
     600                 :            : {
     601                 :          0 :         return &ip4_rewrite_node;
     602                 :            : }
     603                 :            : 
     604                 :        253 : RTE_NODE_REGISTER(ip4_rewrite_node);
     605                 :            : 
     606                 :            : /* IP4 output arc */
     607                 :            : static struct rte_graph_feature_arc_register ip4_output_arc = {
     608                 :            :         .arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
     609                 :            : 
     610                 :            :         /* This arc works on all ethdevs */
     611                 :            :         .max_indexes = RTE_IP4_OUTPUT_ARC_INDEXES,
     612                 :            : 
     613                 :            :         .start_node = &ip4_rewrite_node,
     614                 :            : 
     615                 :            :         /* overwrites start_node->process() function with following only if
     616                 :            :          * application calls rte_graph_feature_arc_init()
     617                 :            :          */
     618                 :            :         .start_node_feature_process_fn = ip4_rewrite_feature_node_process,
     619                 :            : 
     620                 :            :         /* end feature node of an arc*/
     621                 :            :         .end_feature = &if_tx_feature,
     622                 :            : };
     623                 :            : 
     624                 :        253 : RTE_GRAPH_FEATURE_ARC_REGISTER(ip4_output_arc);

Generated by: LCOV version 1.14