/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
#include "log.h"
#include "mbuf_utils.h"
#include "handle_master.h"
+#include "defines.h"
static void buf_pkt_single(struct task_base *tbase, struct rte_mbuf *mbuf, const uint8_t out)
{
}
#define MAX_PMD_TX 32
+void store_packet(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ // If buffer is full, drop the first mbuf
+ if (tbase->aux->mbuf)
+ tx_drop(tbase->aux->mbuf);
+ tbase->aux->mbuf = mbuf;
+}
+
+int tx_pkt_ndp(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
+{
+ struct ipv6_addr ip_dst;
+ int first = 0, ret, ok = 0, rc;
+ const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
+ struct rte_mbuf *mbuf = NULL; // used when one need to send both an ARP and a mbuf
+ uint16_t vlan;
+ uint64_t tsc = rte_rdtsc();
+
+ for (int j = 0; j < n_pkts; j++) {
+ if ((out) && (out[j] >= OUT_HANDLED))
+ continue;
+ if (unlikely((rc = write_ip6_dst_mac(tbase, mbufs[j], &ip_dst, &vlan, tsc)) != SEND_MBUF)) {
+ if (j - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, j - first, out);
+ ok += ret;
+ }
+ first = j + 1;
+ switch(rc) {
+ case SEND_ARP_ND:
+ // Original mbuf (packet) is stored to be sent later -> need to allocate new mbuf
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ store_packet(tbase, mbufs[j]);
+ mbuf->port = tbase->l3.reachable_port_id;
+ tx_ring_cti6(tbase, tbase->l3.ctrl_plane_ring, IP6_REQ_MAC_TO_MASTER, mbuf, tbase->l3.core_id, tbase->l3.task_id, &ip_dst, vlan);
+ } else {
+ plog_err("Failed to get a mbuf from arp/nd mempool\n");
+ tx_drop(mbufs[j]);
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ }
+ break;
+ case SEND_MBUF_AND_ARP_ND:
+ // We send the mbuf and an ND - we need to allocate another mbuf for ND
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ mbuf->port = tbase->l3.reachable_port_id;
+ tx_ring_cti6(tbase, tbase->l3.ctrl_plane_ring, IP6_REQ_MAC_TO_MASTER, mbuf, tbase->l3.core_id, tbase->l3.task_id, &ip_dst, vlan);
+ } else {
+ plog_err("Failed to get a mbuf from arp/nd mempool\n");
+ // We still send the initial mbuf
+ }
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + j, 1, out);
+ break;
+ case DROP_MBUF:
+ tx_drop(mbufs[j]);
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ break;
+ }
+ }
+ }
+ if (n_pkts - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, n_pkts - first, out);
+ ok += ret;
+ }
+ return ok;
+}
int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
{
uint32_t ip_dst;
+ uint16_t vlan;
int first = 0, ret, ok = 0, rc;
const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
struct rte_mbuf *arp_mbuf = NULL; // used when one need to send both an ARP and a mbuf
uint64_t *time;
+ uint64_t tsc = rte_rdtsc();
for (int j = 0; j < n_pkts; j++) {
if ((out) && (out[j] >= OUT_HANDLED))
continue;
- if (unlikely((rc = write_dst_mac(tbase, mbufs[j], &ip_dst, &time)) != SEND_MBUF)) {
+ if (unlikely((rc = write_dst_mac(tbase, mbufs[j], &ip_dst, &vlan, &time, tsc)) != SEND_MBUF)) {
if (j - first) {
ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, j - first, out);
ok += ret;
}
first = j + 1;
switch(rc) {
- case SEND_ARP:
+ case SEND_ARP_ND:
// We re-use the mbuf - no need to create a arp_mbuf and delete the existing mbuf
mbufs[j]->port = tbase->l3.reachable_port_id;
- if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, REQ_MAC_TO_CTRL, mbufs[j], tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
- update_arp_update_time(&tbase->l3, time, 1000);
+ if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, IP4_REQ_MAC_TO_MASTER, mbufs[j], tbase->l3.core_id, tbase->l3.task_id, ip_dst, vlan) == 0)
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 1000);
else
- update_arp_update_time(&tbase->l3, time, 100);
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 100);
break;
- case SEND_MBUF_AND_ARP:
+ case SEND_MBUF_AND_ARP_ND:
// We send the mbuf and an ARP - we need to allocate another mbuf for ARP
- ret = rte_mempool_get(tbase->l3.arp_pool, (void **)&arp_mbuf);
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&arp_mbuf);
if (likely(ret == 0)) {
arp_mbuf->port = tbase->l3.reachable_port_id;
- if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, REQ_MAC_TO_CTRL, arp_mbuf, tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
- update_arp_update_time(&tbase->l3, time, 1000);
+ if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, IP4_REQ_MAC_TO_MASTER, arp_mbuf, tbase->l3.core_id, tbase->l3.task_id, ip_dst, vlan) == 0)
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 1000);
else
- update_arp_update_time(&tbase->l3, time, 100);
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 100);
} else {
plog_err("Failed to get a mbuf from arp mempool\n");
// We still send the initial mbuf
}
}
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
}
void flush_queues_sw(struct task_base *tbase)
ring_enq_drop(tbase->tx_params_sw.tx_rings[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), prod - cons, tbase);
}
}
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
}
void flush_queues_no_drop_hw(struct task_base *tbase)
}
}
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
}
void flush_queues_no_drop_sw(struct task_base *tbase)
ring_enq_no_drop(tbase->tx_params_sw.tx_rings[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), prod - cons, tbase);
}
}
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
}
/* "try" functions try to send packets to sw/hw w/o failing or blocking;
cons = tbase->ws_mbuf->idx[0].cons;
if ((uint16_t)(prod - cons)){
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[0].prod = 0;
tbase->ws_mbuf->idx[0].cons = 0;
ret+= txhw_no_drop(&tbase->tx_params_hw.tx_port_queue[0], tbase->ws_mbuf->mbuf[0] + (cons & WS_MBUF_MASK), (uint16_t)(prod - cons), tbase);
cons = tbase->ws_mbuf->idx[0].cons;
if ((uint16_t)(prod - cons)){
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[0].prod = 0;
tbase->ws_mbuf->idx[0].cons = 0;
ret+= txhw_drop(&tbase->tx_params_hw.tx_port_queue[0], tbase->ws_mbuf->mbuf[0] + (cons & WS_MBUF_MASK), (uint16_t)(prod - cons), tbase);
cons = tbase->ws_mbuf->idx[i].cons;
if (((uint16_t)(prod - cons)) >= MAX_PKT_BURST) {
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[i].cons = cons + MAX_PKT_BURST;
ret+= txhw_no_drop(&tbase->tx_params_hw.tx_port_queue[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), MAX_PKT_BURST, tbase);
}
cons = tbase->ws_mbuf->idx[i].cons;
if (((uint16_t)(prod - cons)) >= MAX_PKT_BURST) {
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[i].cons = cons + MAX_PKT_BURST;
ret += ring_enq_no_drop(tbase->tx_params_sw.tx_rings[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), MAX_PKT_BURST, tbase);
}
cons = tbase->ws_mbuf->idx[i].cons;
if (((uint16_t)(prod - cons)) >= MAX_PKT_BURST) {
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[i].cons = cons + MAX_PKT_BURST;
ret += txhw_drop(&tbase->tx_params_hw.tx_port_queue[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), MAX_PKT_BURST, tbase);
}
cons = tbase->ws_mbuf->idx[i].cons;
if (((uint16_t)(prod - cons)) >= MAX_PKT_BURST) {
- tbase->flags &= ~FLAG_TX_FLUSH;
+ tbase->flags &= ~TBASE_FLAG_TX_FLUSH;
tbase->ws_mbuf->idx[i].cons = cons + MAX_PKT_BURST;
ret+= ring_enq_drop(tbase->tx_params_sw.tx_rings[i], tbase->ws_mbuf->mbuf[i] + (cons & WS_MBUF_MASK), MAX_PKT_BURST, tbase);
}
static void unset_trace(struct task_base *tbase)
{
if (0 == tbase->aux->task_rt_dump.n_trace) {
- if (tbase->tx_pkt == tx_pkt_l3) {
+ if ((tbase->tx_pkt == tx_pkt_l3) || (tbase->tx_pkt == tx_pkt_ndp)){
tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
tbase->aux->tx_pkt_orig = NULL;
} else {
ret = tbase->aux->tx_pkt_orig(tbase, mbufs, n_pkts, out);
if (0 == tbase->aux->task_rt_dump.n_print_tx) {
- if (tbase->tx_pkt == tx_pkt_l3) {
+ if ((tbase->tx_pkt == tx_pkt_l3) || (tbase->tx_pkt == tx_pkt_ndp)) {
tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
tbase->aux->tx_pkt_orig = NULL;
} else {
return ring_enq_no_drop(tbase->tx_params_sw.tx_rings[0], mbufs, n_pkts, tbase);
}
-static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
{
if (tbase->aux->task_rt_dump.cur_trace) {
trace_one_rx_pkt(tbase, mbuf);
}
- mbuf->udata64 = ((uint64_t)ip << 32) | (core_id << 16) | (task_id << 8) | command;
+ ctrl_ring_set_command_core_task_ip(mbuf, ((uint64_t)ip << 32) | (core_id << 16) | (task_id << 8) | command);
return rte_ring_enqueue(ring, mbuf);
}
-int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip, uint16_t vlan)
{
plogx_dbg("\tSending command %s with ip %d.%d.%d.%d to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IP4(ip), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ ctrl_ring_set_vlan(mbuf, vlan);
int ret = tx_ring_all(tbase, ring, command, mbuf, core_id, task_id, ip);
if (unlikely(ret != 0)) {
plogx_dbg("\tFail to send command %s with ip %d.%d.%d.%d to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IP4(ip), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
return ret;
}
-void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint32_t ip)
+void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint32_t ip)
{
plogx_dbg("\tSending command %s with ip %d.%d.%d.%d to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IP4(ip), ring, mbuf, rte_ring_free_count(ring));
int ret = tx_ring_all(tbase, ring, command, mbuf, 0, 0, ip);
{
uint8_t command;
if (add)
- command = ROUTE_ADD_FROM_CTRL;
+ command = ROUTE_ADD_FROM_MASTER;
else
- command = ROUTE_DEL_FROM_CTRL;
+ command = ROUTE_DEL_FROM_MASTER;
plogx_dbg("\tSending command %s to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ring, mbuf, rte_ring_free_count(ring));
ctrl_ring_set_command(mbuf, command);
}
}
-void ctrl_ring_set_command(struct rte_mbuf *mbuf, uint64_t udata64)
+void tx_ring_cti6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, struct ipv6_addr *ip, uint16_t vlan)
{
- mbuf->udata64 = udata64;
-}
-
-uint64_t ctrl_ring_get_command(struct rte_mbuf *mbuf)
-{
- return mbuf->udata64;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command_core_task_ip(mbuf, (core_id << 16) | (task_id << 8) | command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ctrl_ring_set_vlan(mbuf, vlan);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_ip(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->ip = udata32;
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
}
-uint32_t ctrl_ring_get_ip(struct rte_mbuf *mbuf)
+void tx_ring_ip6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip)
{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->ip;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command(mbuf, command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_gateway_ip(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->gateway_ip = udata32;
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
}
-uint32_t ctrl_ring_get_gateway_ip(struct rte_mbuf *mbuf)
+void tx_ring_ip6_data(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip, uint64_t data)
{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->gateway_ip;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command(mbuf, command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ctrl_ring_set_data(mbuf, data);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_prefix(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->prefix = udata32;
-}
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
-uint32_t ctrl_ring_get_prefix(struct rte_mbuf *mbuf)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->prefix;
}