summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/tx_pkt.c
diff options
context:
space:
mode:
authorXavier Simonart <xavier.simonart@intel.com>2020-05-11 21:00:33 +0200
committerXavier Simonart <xavier.simonart@intel.com>2020-05-29 23:45:09 +0200
commitc871c361f9d69a93429ae385e7dbf21a46aa6857 (patch)
tree957ec8a53d2cd0a9b5676e163c22e8a3ae8f6f3e /VNFs/DPPD-PROX/tx_pkt.c
parent7c4601f23c526b14a67674782b303663dfaa95af (diff)
Added initial support for NDP (IPv6)
Following messages are now handled by PROX - router_solicitation - neighbour_solicitation - router_advertisement - neighbour_advertisement The following parameters are supported (through the PROX config file) - sub mode=ndp This will enable handling of router and neighbour solicitation and advertisement. - local ipv6=xxxx:xxxx:xxxxx:xxxx:xxxx:xxxx:xxxx:xxxx This will configure the local IPv6 address of the port. This parameter is optional. If not specified, the local IPv6 will be calculated from the EUI. - global ipv6=xxxx:xxxx:xxxxx:xxxx:xxxx:xxxx:xxxx:xxxx This will configure the global IPv6 address of the port. This parameter is optional. If not specified, the global IPv6 will be calculated from the EUI and the router prefix received from the router. - ipv6 router=yes This will cause the core to behave as an IPv6 router i.e. it will generate Router Advertisement messages This is only useful in back to back cases, when no real IPv6 router is present in the setup. - router prefix=xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx The router prefix usedin the router advertisement The prefix will be used by the node to build an IPv6 global address in cases none were configured. "Unsollicited NA" parameter has been added within the core/task section. If set to yes (Unsollicited NA=yes), then an unsollicited neighbour Advertisement is sent at startup A same core/task cannot support both l3 and ndp mode. Those messages will be generated or handled when submode is set to "ndp": - neighbour sollicitation - neighbour advertisement - router sollicitation - router advertisement An example configuration is provided: config/ipv6.cfg in which port 0 / core 1 plays the role of the generator and port 1 / core 2 plays the role of the swap. Change-Id: Id0ab32d384448b4cf767fb4a1c486fc023f4f395 Signed-off-by: Xavier Simonart <xavier.simonart@intel.com>
Diffstat (limited to 'VNFs/DPPD-PROX/tx_pkt.c')
-rw-r--r--VNFs/DPPD-PROX/tx_pkt.c177
1 files changed, 126 insertions, 51 deletions
diff --git a/VNFs/DPPD-PROX/tx_pkt.c b/VNFs/DPPD-PROX/tx_pkt.c
index 51c1afa7..60d6b514 100644
--- a/VNFs/DPPD-PROX/tx_pkt.c
+++ b/VNFs/DPPD-PROX/tx_pkt.c
@@ -1,5 +1,5 @@
/*
-// 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.
@@ -26,6 +26,7 @@
#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)
{
@@ -50,6 +51,70 @@ static inline void buf_pkt_all(struct task_base *tbase, struct rte_mbuf **mbufs,
}
#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)
+{
+ // TODO NDP
+ 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
+
+ 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)) != 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);
+ } 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);
+ } 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;
@@ -69,23 +134,23 @@ int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts,
}
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) == 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) == 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
@@ -644,7 +709,7 @@ static inline void trace_one_tx_pkt(struct task_base *tbase, struct rte_mbuf *mb
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 {
@@ -713,7 +778,7 @@ int tx_pkt_dump(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkt
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 {
@@ -804,16 +869,16 @@ int tx_ctrlplane_sw(struct task_base *tbase, struct rte_mbuf **mbufs, const uint
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)
{
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));
int ret = tx_ring_all(tbase, ring, command, mbuf, core_id, task_id, ip);
@@ -825,7 +890,7 @@ int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command
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);
@@ -851,9 +916,9 @@ void tx_ring_route(struct task_base *tbase, struct rte_ring *ring, int add, stru
{
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);
@@ -871,48 +936,58 @@ void tx_ring_route(struct task_base *tbase, struct rte_ring *ring, int add, stru
}
}
-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)
{
- 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);
+ 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;
}