26 #include <rte_ethdev.h>
27 #include <rte_ether.h>
30 #include <netinet/icmp6.h>
41 #define MAX_RX_BURST_SIZE 256
54 struct rte_ipv6_hdr *ipv6_hdr;
55 struct rte_flow_item_icmp6_nd_ns *icmp6_ns_hdr;
60 ipv6_hdr = (
struct rte_ipv6_hdr *)((
char *)eth_hdr +
sizeof(rte_ether_hdr));
61 if (ipv6_hdr->proto != IPPROTO_ICMPV6) {
64 icmp6_ns_hdr = (
struct rte_flow_item_icmp6_nd_ns *)(ipv6_hdr + 1);
65 uint16_t ns_op = icmp6_ns_hdr->type;
66 if (ns_op != ND_NEIGHBOR_SOLICIT) {
87 rte_ether_addr *port_src_mac,
88 struct rte_mbuf *packet)
90 struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(packet,
struct rte_ether_hdr *);
91 uint16_t
ether_type = htons(eth_hdr->ether_type);
92 uint32_t pkt_meta = rte_flow_dynf_metadata_get(packet);
96 if (is_ingress_sampled || is_egress_sampled) {
98 DOCA_LOG_INFO(
"SAMPLED PACKET: port %d, queue_id %d, pkt_meta 0x%x, %s",
102 is_ingress_sampled ?
"INGRESS" :
"EGRESS");
103 rte_pktmbuf_dump(stdout, packet, packet->data_len);
109 rte_pktmbuf_dump(stdout, packet, packet->data_len);
138 uint32_t lcore_id = rte_lcore_id();
142 rte_exit(EXIT_FAILURE,
"Unexpectedly entered RSS handler from main thread\n");
149 double tsc_to_seconds = 1.0 / (double)rte_get_timer_hz();
153 while (!*params->force_quit) {
154 uint16_t port_id = params->pf_dev->port_id;
155 uint64_t t_start = rte_rdtsc();
162 for (
int i = 0; i < nb_rx_packets && !*params->force_quit; i++) {
166 rte_pktmbuf_free_bulk(rx_packets, nb_rx_packets);
168 if (params->config->show_rss_durations) {
169 double sec = (double)(rte_rdtsc() - t_start) * tsc_to_seconds;
170 DOCA_LOG_INFO(
"L-Core %d port %d: processed %d packets in %f seconds",
184 uint32_t lcore_id = rte_lcore_id();
193 nsent = rte_eth_tx_burst(port_id,
queue_id, &packet, 1);
202 rte_ether_addr *port_src_mac,
203 const struct rte_mbuf *request_pkt,
204 uint32_t arp_response_meta_flag)
206 const struct rte_ether_hdr *request_eth_hdr = rte_pktmbuf_mtod(request_pkt,
struct rte_ether_hdr *);
207 const struct rte_arp_hdr *request_arp_hdr = (rte_arp_hdr *)&request_eth_hdr[1];
209 uint16_t arp_op = RTE_BE16(request_arp_hdr->arp_opcode);
210 if (arp_op != RTE_ARP_OP_REQUEST) {
211 DOCA_LOG_ERR(
"RSS ARP Handler: expected op %d, got %d", RTE_ARP_OP_REQUEST, arp_op);
215 struct rte_mbuf *response_pkt = rte_pktmbuf_alloc(mpool);
217 DOCA_LOG_ERR(
"Out of memory for ARP response packets; exiting");
221 *RTE_MBUF_DYNFIELD(response_pkt, rte_flow_dynf_metadata_offs, uint32_t *) = arp_response_meta_flag;
222 response_pkt->ol_flags |= rte_flow_dynf_metadata_mask;
224 uint32_t pkt_size =
sizeof(
struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);
225 response_pkt->data_len = pkt_size;
226 response_pkt->pkt_len = pkt_size;
228 struct rte_ether_hdr *response_eth_hdr = rte_pktmbuf_mtod(response_pkt,
struct rte_ether_hdr *);
229 struct rte_arp_hdr *response_arp_hdr = (rte_arp_hdr *)&response_eth_hdr[1];
231 memcpy(&response_eth_hdr->src_addr, port_src_mac, RTE_ETHER_ADDR_LEN);
232 response_eth_hdr->dst_addr = request_eth_hdr->src_addr;
235 response_arp_hdr->arp_hardware = RTE_BE16(RTE_ARP_HRD_ETHER);
236 response_arp_hdr->arp_protocol = RTE_BE16(RTE_ETHER_TYPE_IPV4);
237 response_arp_hdr->arp_hlen = RTE_ETHER_ADDR_LEN;
238 response_arp_hdr->arp_plen =
sizeof(uint32_t);
239 response_arp_hdr->arp_opcode = RTE_BE16(RTE_ARP_OP_REPLY);
240 memcpy(&response_arp_hdr->arp_data.arp_sha, port_src_mac, RTE_ETHER_ADDR_LEN);
241 response_arp_hdr->arp_data.arp_tha = request_arp_hdr->arp_data.arp_sha;
242 response_arp_hdr->arp_data.arp_sip = request_arp_hdr->arp_data.arp_tip;
243 response_arp_hdr->arp_data.arp_tip = request_arp_hdr->arp_data.arp_sip;
245 uint16_t nb_tx_packets = 0;
246 while (nb_tx_packets < 1) {
248 nb_tx_packets = rte_eth_tx_burst(port_id,
queue_id, &response_pkt, 1);
249 if (nb_tx_packets != 1) {
250 DOCA_LOG_WARN(
"ARP reinject: rte_eth_tx_burst returned %d", nb_tx_packets);
254 char ip_addr_str[INET_ADDRSTRLEN];
255 inet_ntop(AF_INET, &request_arp_hdr->arp_data.arp_tip, ip_addr_str, INET_ADDRSTRLEN);
256 DOCA_LOG_DBG(
"Port %d replied to ARP request for IP %s", port_id, ip_addr_str);
264 rte_ether_addr *port_src_mac,
265 const struct rte_mbuf *request_pkt,
266 uint32_t na_response_meta_flag)
268 uint8_t option_header_size = RTE_ETHER_ADDR_LEN + 2;
269 const struct rte_ether_hdr *request_eth_hdr = rte_pktmbuf_mtod(request_pkt,
struct rte_ether_hdr *);
272 struct rte_ipv6_hdr *request_ipv6_hdr =
273 (
struct rte_ipv6_hdr *)((
char *)request_eth_hdr +
sizeof(rte_ether_hdr));
274 struct rte_flow_item_icmp6_nd_ns *request_icmp6_ns_hdr =
275 (
struct rte_flow_item_icmp6_nd_ns *)(request_ipv6_hdr + 1);
277 struct rte_mbuf *response_pkt = rte_pktmbuf_alloc(mpool);
279 DOCA_LOG_ERR(
"Out of memory for NS response packets; exiting");
283 *RTE_MBUF_DYNFIELD(response_pkt, rte_flow_dynf_metadata_offs, uint32_t *) = na_response_meta_flag;
284 response_pkt->ol_flags |= rte_flow_dynf_metadata_mask;
286 uint32_t pkt_size =
sizeof(
struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) +
287 sizeof(struct rte_flow_item_icmp6_nd_na) + option_header_size;
288 response_pkt->data_len = pkt_size;
289 response_pkt->pkt_len = pkt_size;
291 struct rte_ether_hdr *response_eth_hdr = rte_pktmbuf_mtod(response_pkt,
struct rte_ether_hdr *);
292 struct rte_ipv6_hdr *response_ipv6_hdr = (
struct rte_ipv6_hdr *)(response_eth_hdr + 1);
293 struct rte_flow_item_icmp6_nd_na *response_na_hdr = (
struct rte_flow_item_icmp6_nd_na *)(response_ipv6_hdr + 1);
295 memcpy(&response_eth_hdr->src_addr, port_src_mac, RTE_ETHER_ADDR_LEN);
296 response_eth_hdr->dst_addr = request_eth_hdr->src_addr;
299 response_ipv6_hdr->vtc_flow = htonl((6 << 28));
300 response_ipv6_hdr->payload_len = RTE_BE16(
sizeof(
struct rte_flow_item_icmp6_nd_ns) + option_header_size);
301 response_ipv6_hdr->proto = IPPROTO_ICMPV6;
302 response_ipv6_hdr->hop_limits = 255;
304 memcpy(response_ipv6_hdr->src_addr, request_icmp6_ns_hdr->target_addr,
IPV6_ADDR_LEN);
306 memcpy(response_ipv6_hdr->dst_addr, request_ipv6_hdr->src_addr,
IPV6_ADDR_LEN);
308 response_na_hdr->type = ND_NEIGHBOR_ADVERT;
309 response_na_hdr->code = 0;
310 response_na_hdr->checksum = 0;
311 memcpy(response_na_hdr->target_addr, request_icmp6_ns_hdr->target_addr,
IPV6_ADDR_LEN);
313 uint8_t *options = (uint8_t *)(response_na_hdr + 1);
316 memcpy(&options[2], port_src_mac, RTE_ETHER_ADDR_LEN);
317 response_na_hdr->checksum = rte_ipv6_udptcp_cksum(response_ipv6_hdr, response_na_hdr);
319 uint16_t nb_tx_packets = 0;
320 while (nb_tx_packets < 1) {
322 nb_tx_packets = rte_eth_tx_burst(port_id,
queue_id, &response_pkt, 1);
323 if (nb_tx_packets != 1) {
324 DOCA_LOG_WARN(
"Neighbor Solicitation reinject: rte_eth_tx_burst returned %d", nb_tx_packets);
328 char ip_addr_str[INET6_ADDRSTRLEN];
329 inet_ntop(AF_INET6, &request_icmp6_ns_hdr->target_addr, ip_addr_str, INET6_ADDRSTRLEN);
330 DOCA_LOG_DBG(
"Port %d replied to Neighbor Solicitation request for IP %s", port_id, ip_addr_str);
doca_error_t handle_miss_packet(struct rte_mbuf *packet)
Handles any "miss" packets received by RSS which indicate a new tunnel connection is needed.
#define DOCA_FLOW_ETHER_TYPE_ARP
#define DOCA_FLOW_ETHER_TYPE_IPV6
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
static constexpr uint32_t IPV6_ADDR_LEN
struct rte_mempool * mbuf_pool
The parameters needed by each L-Core's main loop.
PSP_GatewayImpl * psp_svc
psp_gw_app_config * config
uint32_t egress_sample_meta_indicator
uint32_t ingress_sample_meta_indicator
struct application_dpdk_config dpdk_config
bool show_sampled_packets
uint32_t return_to_vf_indicator