dpdk/examples/l3fwd/l3fwd_em_hlm.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2016-2018 Intel Corporation.
   3 * Copyright(c) 2017-2018 Linaro Limited.
   4 */
   5
   6#ifndef __L3FWD_EM_HLM_H__
   7#define __L3FWD_EM_HLM_H__
   8
   9#if defined RTE_ARCH_X86
  10#include "l3fwd_sse.h"
  11#include "l3fwd_em_hlm_sse.h"
  12#elif defined __ARM_NEON
  13#include "l3fwd_neon.h"
  14#include "l3fwd_em_hlm_neon.h"
  15#endif
  16
  17#ifdef RTE_ARCH_ARM64
  18#define EM_HASH_LOOKUP_COUNT 16
  19#else
  20#define EM_HASH_LOOKUP_COUNT 8
  21#endif
  22
  23
  24static __rte_always_inline void
  25em_get_dst_port_ipv4xN(struct lcore_conf *qconf, struct rte_mbuf *m[],
  26                uint16_t portid, uint16_t dst_port[])
  27{
  28        int i;
  29        int32_t ret[EM_HASH_LOOKUP_COUNT];
  30        union ipv4_5tuple_host key[EM_HASH_LOOKUP_COUNT];
  31        const void *key_array[EM_HASH_LOOKUP_COUNT];
  32
  33        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  34                get_ipv4_5tuple(m[i], mask0.x, &key[i]);
  35                key_array[i] = &key[i];
  36        }
  37
  38        rte_hash_lookup_bulk(qconf->ipv4_lookup_struct, &key_array[0],
  39                             EM_HASH_LOOKUP_COUNT, ret);
  40
  41        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  42                dst_port[i] = ((ret[i] < 0) ?
  43                                portid : ipv4_l3fwd_out_if[ret[i]]);
  44
  45                if (dst_port[i] >= RTE_MAX_ETHPORTS ||
  46                                (enabled_port_mask & 1 << dst_port[i]) == 0)
  47                        dst_port[i] = portid;
  48        }
  49}
  50
  51static __rte_always_inline void
  52em_get_dst_port_ipv6xN(struct lcore_conf *qconf, struct rte_mbuf *m[],
  53                uint16_t portid, uint16_t dst_port[])
  54{
  55        int i;
  56        int32_t ret[EM_HASH_LOOKUP_COUNT];
  57        union ipv6_5tuple_host key[EM_HASH_LOOKUP_COUNT];
  58        const void *key_array[EM_HASH_LOOKUP_COUNT];
  59
  60        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  61                get_ipv6_5tuple(m[i], mask1.x, mask2.x, &key[i]);
  62                key_array[i] = &key[i];
  63        }
  64
  65        rte_hash_lookup_bulk(qconf->ipv6_lookup_struct, &key_array[0],
  66                             EM_HASH_LOOKUP_COUNT, ret);
  67
  68        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  69                dst_port[i] = ((ret[i] < 0) ?
  70                                portid : ipv6_l3fwd_out_if[ret[i]]);
  71
  72                if (dst_port[i] >= RTE_MAX_ETHPORTS ||
  73                                (enabled_port_mask & 1 << dst_port[i]) == 0)
  74                        dst_port[i] = portid;
  75        }
  76}
  77
  78static __rte_always_inline void
  79em_get_dst_port_ipv4xN_events(struct lcore_conf *qconf, struct rte_mbuf *m[],
  80                              uint16_t dst_port[])
  81{
  82        int i;
  83        int32_t ret[EM_HASH_LOOKUP_COUNT];
  84        union ipv4_5tuple_host key[EM_HASH_LOOKUP_COUNT];
  85        const void *key_array[EM_HASH_LOOKUP_COUNT];
  86
  87        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  88                get_ipv4_5tuple(m[i], mask0.x, &key[i]);
  89                key_array[i] = &key[i];
  90        }
  91
  92        rte_hash_lookup_bulk(qconf->ipv4_lookup_struct, &key_array[0],
  93                             EM_HASH_LOOKUP_COUNT, ret);
  94
  95        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
  96                dst_port[i] = ((ret[i] < 0) ?
  97                                m[i]->port : ipv4_l3fwd_out_if[ret[i]]);
  98
  99                if (dst_port[i] >= RTE_MAX_ETHPORTS ||
 100                                (enabled_port_mask & 1 << dst_port[i]) == 0)
 101                        dst_port[i] = m[i]->port;
 102        }
 103}
 104
 105static __rte_always_inline void
 106em_get_dst_port_ipv6xN_events(struct lcore_conf *qconf, struct rte_mbuf *m[],
 107                              uint16_t dst_port[])
 108{
 109        int i;
 110        int32_t ret[EM_HASH_LOOKUP_COUNT];
 111        union ipv6_5tuple_host key[EM_HASH_LOOKUP_COUNT];
 112        const void *key_array[EM_HASH_LOOKUP_COUNT];
 113
 114        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
 115                get_ipv6_5tuple(m[i], mask1.x, mask2.x, &key[i]);
 116                key_array[i] = &key[i];
 117        }
 118
 119        rte_hash_lookup_bulk(qconf->ipv6_lookup_struct, &key_array[0],
 120                             EM_HASH_LOOKUP_COUNT, ret);
 121
 122        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
 123                dst_port[i] = ((ret[i] < 0) ?
 124                                m[i]->port : ipv6_l3fwd_out_if[ret[i]]);
 125
 126                if (dst_port[i] >= RTE_MAX_ETHPORTS ||
 127                                (enabled_port_mask & 1 << dst_port[i]) == 0)
 128                        dst_port[i] = m[i]->port;
 129        }
 130}
 131
 132static __rte_always_inline uint16_t
 133em_get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
 134                uint16_t portid)
 135{
 136        uint16_t next_hop;
 137        struct rte_ipv4_hdr *ipv4_hdr;
 138        struct rte_ipv6_hdr *ipv6_hdr;
 139        uint32_t tcp_or_udp;
 140        uint32_t l3_ptypes;
 141
 142        tcp_or_udp = pkt->packet_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
 143        l3_ptypes = pkt->packet_type & RTE_PTYPE_L3_MASK;
 144
 145        if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV4)) {
 146
 147                /* Handle IPv4 headers.*/
 148                ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *,
 149                                sizeof(struct rte_ether_hdr));
 150
 151                next_hop = em_get_ipv4_dst_port(ipv4_hdr, portid,
 152                                qconf->ipv4_lookup_struct);
 153
 154                if (next_hop >= RTE_MAX_ETHPORTS ||
 155                                (enabled_port_mask & 1 << next_hop) == 0)
 156                        next_hop = portid;
 157
 158                return next_hop;
 159
 160        } else if (tcp_or_udp && (l3_ptypes == RTE_PTYPE_L3_IPV6)) {
 161
 162                /* Handle IPv6 headers.*/
 163                ipv6_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *,
 164                                sizeof(struct rte_ether_hdr));
 165
 166                next_hop = em_get_ipv6_dst_port(ipv6_hdr, portid,
 167                                qconf->ipv6_lookup_struct);
 168
 169                if (next_hop >= RTE_MAX_ETHPORTS ||
 170                                (enabled_port_mask & 1 << next_hop) == 0)
 171                        next_hop = portid;
 172
 173                return next_hop;
 174
 175        }
 176
 177        return portid;
 178}
 179
 180/*
 181 * Buffer optimized handling of packets, invoked
 182 * from main_loop.
 183 */
 184static inline void
 185l3fwd_em_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
 186                uint16_t portid, struct lcore_conf *qconf)
 187{
 188        int32_t i, j, pos;
 189        uint16_t dst_port[MAX_PKT_BURST];
 190
 191        /*
 192         * Send nb_rx - nb_rx % EM_HASH_LOOKUP_COUNT packets
 193         * in groups of EM_HASH_LOOKUP_COUNT.
 194         */
 195        int32_t n = RTE_ALIGN_FLOOR(nb_rx, EM_HASH_LOOKUP_COUNT);
 196
 197        for (j = 0; j < EM_HASH_LOOKUP_COUNT && j < nb_rx; j++) {
 198                rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j],
 199                                               struct rte_ether_hdr *) + 1);
 200        }
 201
 202        for (j = 0; j < n; j += EM_HASH_LOOKUP_COUNT) {
 203
 204                uint32_t pkt_type = RTE_PTYPE_L3_MASK |
 205                                    RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP;
 206                uint32_t l3_type, tcp_or_udp;
 207
 208                for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++)
 209                        pkt_type &= pkts_burst[j + i]->packet_type;
 210
 211                l3_type = pkt_type & RTE_PTYPE_L3_MASK;
 212                tcp_or_udp = pkt_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
 213
 214                for (i = 0, pos = j + EM_HASH_LOOKUP_COUNT;
 215                     i < EM_HASH_LOOKUP_COUNT && pos < nb_rx; i++, pos++) {
 216                        rte_prefetch0(rte_pktmbuf_mtod(
 217                                        pkts_burst[pos],
 218                                        struct rte_ether_hdr *) + 1);
 219                }
 220
 221                if (tcp_or_udp && (l3_type == RTE_PTYPE_L3_IPV4)) {
 222
 223                        em_get_dst_port_ipv4xN(qconf, &pkts_burst[j], portid,
 224                                               &dst_port[j]);
 225
 226                } else if (tcp_or_udp && (l3_type == RTE_PTYPE_L3_IPV6)) {
 227
 228                        em_get_dst_port_ipv6xN(qconf, &pkts_burst[j], portid,
 229                                               &dst_port[j]);
 230
 231                } else {
 232                        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++)
 233                                dst_port[j + i] = em_get_dst_port(qconf,
 234                                                pkts_burst[j + i], portid);
 235                }
 236        }
 237
 238        for (; j < nb_rx; j++)
 239                dst_port[j] = em_get_dst_port(qconf, pkts_burst[j], portid);
 240
 241        send_packets_multi(qconf, pkts_burst, dst_port, nb_rx);
 242
 243}
 244
 245/*
 246 * Buffer optimized handling of events, invoked
 247 * from main_loop.
 248 */
 249static inline void
 250l3fwd_em_process_events(int nb_rx, struct rte_event **ev,
 251                     struct lcore_conf *qconf)
 252{
 253        int32_t i, j, pos;
 254        uint16_t dst_port[MAX_PKT_BURST];
 255        struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 256
 257        /*
 258         * Send nb_rx - nb_rx % EM_HASH_LOOKUP_COUNT packets
 259         * in groups of EM_HASH_LOOKUP_COUNT.
 260         */
 261        int32_t n = RTE_ALIGN_FLOOR(nb_rx, EM_HASH_LOOKUP_COUNT);
 262
 263        for (j = 0; j < EM_HASH_LOOKUP_COUNT && j < nb_rx; j++) {
 264                pkts_burst[j] = ev[j]->mbuf;
 265                rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j],
 266                                               struct rte_ether_hdr *) + 1);
 267        }
 268
 269        for (j = 0; j < n; j += EM_HASH_LOOKUP_COUNT) {
 270
 271                uint32_t pkt_type = RTE_PTYPE_L3_MASK |
 272                                    RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP;
 273                uint32_t l3_type, tcp_or_udp;
 274
 275                for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++)
 276                        pkt_type &= pkts_burst[j + i]->packet_type;
 277
 278                l3_type = pkt_type & RTE_PTYPE_L3_MASK;
 279                tcp_or_udp = pkt_type & (RTE_PTYPE_L4_TCP | RTE_PTYPE_L4_UDP);
 280
 281                for (i = 0, pos = j + EM_HASH_LOOKUP_COUNT;
 282                     i < EM_HASH_LOOKUP_COUNT && pos < nb_rx; i++, pos++) {
 283                        rte_prefetch0(rte_pktmbuf_mtod(
 284                                        pkts_burst[pos],
 285                                        struct rte_ether_hdr *) + 1);
 286                }
 287
 288                if (tcp_or_udp && (l3_type == RTE_PTYPE_L3_IPV4)) {
 289
 290                        em_get_dst_port_ipv4xN_events(qconf, &pkts_burst[j],
 291                                               &dst_port[j]);
 292
 293                } else if (tcp_or_udp && (l3_type == RTE_PTYPE_L3_IPV6)) {
 294
 295                        em_get_dst_port_ipv6xN_events(qconf, &pkts_burst[j],
 296                                               &dst_port[j]);
 297
 298                } else {
 299                        for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++) {
 300                                pkts_burst[j + i]->port = em_get_dst_port(qconf,
 301                                                pkts_burst[j + i],
 302                                                pkts_burst[j + i]->port);
 303                                process_packet(pkts_burst[j + i],
 304                                                &pkts_burst[j + i]->port);
 305                        }
 306                        continue;
 307                }
 308                processx4_step3(&pkts_burst[j], &dst_port[j]);
 309
 310                for (i = 0; i < EM_HASH_LOOKUP_COUNT; i++)
 311                        pkts_burst[j + i]->port = dst_port[j + i];
 312
 313        }
 314
 315        for (; j < nb_rx; j++) {
 316                pkts_burst[j]->port = em_get_dst_port(qconf, pkts_burst[j],
 317                                                      pkts_burst[j]->port);
 318                process_packet(pkts_burst[j], &pkts_burst[j]->port);
 319        }
 320}
 321#endif /* __L3FWD_EM_HLM_H__ */
 322