diff --git a/docs/graph.svg b/docs/graph.svg
index 514a71ba6..9bada694d 100644
--- a/docs/graph.svg
+++ b/docs/graph.svg
@@ -699,7 +699,7 @@
-
+
icmp6_output
icmp6_output
@@ -746,24 +746,24 @@
-
-
-icmp6_output->ip6_output
-
-
-
-
+
icmp6_local_send
icmp6_local_send
-
+
icmp6_local_send->icmp6_output
+
+
+icmp6_output->ip6_output
+
+
+
ndp_na_output
diff --git a/modules/infra/control/bond.c b/modules/infra/control/bond.c
index 6432c4c53..2c0c913a0 100644
--- a/modules/infra/control/bond.c
+++ b/modules/infra/control/bond.c
@@ -415,9 +415,8 @@ static void bond_to_api(void *info, const struct iface *iface) {
}
}
-static struct iface_type iface_type_bond = {
+static const struct iface_type iface_type_bond = {
.id = GR_IFACE_TYPE_BOND,
- .name = "bond",
.pub_size = sizeof(struct gr_iface_info_bond),
.priv_size = sizeof(struct iface_info_bond),
.init = bond_init,
diff --git a/modules/infra/control/gr_iface.h b/modules/infra/control/gr_iface.h
index e7b3d7cb8..038a78deb 100644
--- a/modules/infra/control/gr_iface.h
+++ b/modules/infra/control/gr_iface.h
@@ -57,11 +57,9 @@ struct iface_type {
int (*set_promisc)(struct iface *, bool enabled);
void (*to_api)(void *api_info, const struct iface *);
void (*metrics_collect)(struct gr_metrics_ctx *, const struct iface *);
- const char *name;
- STAILQ_ENTRY(iface_type) next;
};
-void iface_type_register(struct iface_type *);
+void iface_type_register(const struct iface_type *);
const struct iface_type *iface_type_get(gr_iface_type_t type_id);
struct iface *iface_create(const struct gr_iface *conf, const void *api_info);
int iface_reconfig(
diff --git a/modules/infra/control/iface.c b/modules/infra/control/iface.c
index d54874fad..d81a84422 100644
--- a/modules/infra/control/iface.c
+++ b/modules/infra/control/iface.c
@@ -22,7 +22,7 @@
#include
#include
-static STAILQ_HEAD(, iface_type) types = STAILQ_HEAD_INITIALIZER(types);
+static const struct iface_type *iface_types[UINT_NUM_VALUES(gr_iface_type_t)];
struct iface_stats iface_stats[MAX_IFACES][RTE_MAX_LCORE];
@@ -42,19 +42,15 @@ static bool iface_type_valid(gr_iface_type_t type) {
}
const struct iface_type *iface_type_get(gr_iface_type_t type_id) {
- struct iface_type *t;
- STAILQ_FOREACH (t, &types, next)
- if (t->id == type_id)
- return t;
- return errno_set_null(ENODEV);
+ return iface_types[type_id];
}
-void iface_type_register(struct iface_type *type) {
+void iface_type_register(const struct iface_type *type) {
if (!iface_type_valid(type->id))
ABORT("invalid iface type id: %u", type->id);
if (iface_type_get(type->id) != NULL)
ABORT("duplicate iface type id: %u", type->id);
- STAILQ_INSERT_TAIL(&types, type, next);
+ iface_types[type->id] = type;
}
#define IFACE_ID_FIRST GR_IFACE_ID_UNDEF + 1
@@ -93,8 +89,10 @@ struct iface *iface_create(const struct gr_iface *conf, const void *api_info) {
bool vrf_ref = false;
uint16_t ifid;
- if (type == NULL)
+ if (type == NULL) {
+ errno = ENODEV;
goto fail;
+ }
if (charset_check(conf->name, GR_IFACE_NAME_SIZE) < 0)
goto fail;
while ((iface = iface_next(GR_IFACE_TYPE_UNDEF, iface)) != NULL) {
diff --git a/modules/infra/control/loopback.c b/modules/infra/control/loopback.c
index a52e523a8..7369d91e0 100644
--- a/modules/infra/control/loopback.c
+++ b/modules/infra/control/loopback.c
@@ -307,9 +307,8 @@ static void loopback_module_fini(struct event_base *) {
static void iface_loopback_to_api(void * /* info */, const struct iface * /* iface */) { }
-static struct iface_type iface_type_loopback = {
+static const struct iface_type iface_type_loopback = {
.id = GR_IFACE_TYPE_LOOPBACK,
- .name = "loopback",
.pub_size = 0,
.priv_size = sizeof(struct iface_info_loopback),
.init = iface_loopback_init,
diff --git a/modules/infra/control/port.c b/modules/infra/control/port.c
index dab5acc87..08190ff55 100644
--- a/modules/infra/control/port.c
+++ b/modules/infra/control/port.c
@@ -810,9 +810,8 @@ static void port_fini(struct event_base *) {
gr_vec_free(reset_ports);
}
-static struct iface_type iface_type_port = {
+static const struct iface_type iface_type_port = {
.id = GR_IFACE_TYPE_PORT,
- .name = "port",
.pub_size = sizeof(struct gr_iface_info_port),
.priv_size = sizeof(struct iface_info_port),
.init = iface_port_init,
diff --git a/modules/infra/control/port_test.c b/modules/infra/control/port_test.c
index 317a78964..cb35a8907 100644
--- a/modules/infra/control/port_test.c
+++ b/modules/infra/control/port_test.c
@@ -20,7 +20,7 @@ struct gr_config gr_config;
struct workers workers;
void gr_register_api_handler(struct gr_api_handler *) { }
void gr_register_module(struct gr_module *) { }
-void iface_type_register(struct iface_type *) { }
+void iface_type_register(const struct iface_type *) { }
void gr_event_push(uint32_t, const void *) { }
void gr_event_subscribe(struct gr_event_subscription *) { }
mock_func(struct rte_mempool *, gr_pktmbuf_pool_get(int8_t, uint32_t));
diff --git a/modules/infra/control/vlan.c b/modules/infra/control/vlan.c
index 0b9c9fe39..b1beb8c2f 100644
--- a/modules/infra/control/vlan.c
+++ b/modules/infra/control/vlan.c
@@ -184,9 +184,8 @@ static void vlan_to_api(void *info, const struct iface *iface) {
*api = vlan->base;
}
-static struct iface_type iface_type_vlan = {
+static const struct iface_type iface_type_vlan = {
.id = GR_IFACE_TYPE_VLAN,
- .name = "vlan",
.pub_size = sizeof(struct gr_iface_info_vlan),
.priv_size = sizeof(struct iface_info_vlan),
.init = iface_vlan_init,
diff --git a/modules/infra/control/worker_test.c b/modules/infra/control/worker_test.c
index 6a9df56a6..d4ccd90a1 100644
--- a/modules/infra/control/worker_test.c
+++ b/modules/infra/control/worker_test.c
@@ -39,7 +39,7 @@ struct gr_config gr_config;
void gr_register_api_handler(struct gr_api_handler *) { }
void gr_register_module(struct gr_module *) { }
void gr_event_subscribe(struct gr_event_subscription *) { }
-void iface_type_register(struct iface_type *) { }
+void iface_type_register(const struct iface_type *) { }
void gr_metrics_ctx_init(struct gr_metrics_ctx *, struct gr_metrics_writer *, ...) { }
void gr_metrics_labels_add(struct gr_metrics_ctx *, ...) { }
void gr_metric_emit(struct gr_metrics_ctx *, const struct gr_metric *, uint64_t) { }
diff --git a/modules/infra/datapath/bond_output.c b/modules/infra/datapath/bond_output.c
index 13c7a701b..6f6abb214 100644
--- a/modules/infra/datapath/bond_output.c
+++ b/modules/infra/datapath/bond_output.c
@@ -202,13 +202,19 @@ bond_select_tx_member(const struct rte_mbuf *m, const struct iface_info_bond *bo
static uint16_t
bond_output_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
const struct iface_info_bond *bond;
- const struct iface *iface, *member;
+ uint16_t packets, last_iface_id;
+ const struct iface *member;
+ struct iface_stats *stats;
rte_edge_t edge;
+ uint64_t bytes;
+
+ last_iface_id = GR_IFACE_ID_UNDEF;
+ packets = 0;
+ bytes = 0;
for (unsigned i = 0; i < nb_objs; i++) {
struct rte_mbuf *mbuf = objs[i];
- iface = mbuf_data(mbuf)->iface;
- bond = iface_info_bond(iface);
+ bond = iface_info_bond(mbuf_data(mbuf)->iface);
// Select output member port
member = bond_select_tx_member(mbuf, bond);
@@ -224,16 +230,30 @@ bond_output_process(struct rte_graph *graph, struct rte_node *node, void **objs,
t->member_iface_id = member->id;
}
- // Update bond statistics
- struct iface_stats *stats = iface_get_stats(rte_lcore_id(), iface->id);
- stats->tx_packets += 1;
- stats->tx_bytes += rte_pktmbuf_pkt_len(mbuf);
+ if (member->id != last_iface_id) {
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+ last_iface_id = member->id;
+ packets = 0;
+ bytes = 0;
+ }
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(mbuf);
edge = PORT_OUTPUT;
next:
rte_node_enqueue_x1(graph, node, edge, mbuf);
}
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/infra/datapath/eth_input.c b/modules/infra/datapath/eth_input.c
index 7cd45adc2..f37248f86 100644
--- a/modules/infra/datapath/eth_input.c
+++ b/modules/infra/datapath/eth_input.c
@@ -22,7 +22,7 @@ enum {
NB_EDGES,
};
-static rte_edge_t l2l3_edges[1 << 16] = {UNKNOWN_ETHER_TYPE};
+static rte_edge_t l2l3_edges[UINT_NUM_VALUES(rte_be16_t)] = {UNKNOWN_ETHER_TYPE};
void gr_eth_input_add_type(rte_be16_t eth_type, const char *next_node) {
LOG(DEBUG, "eth_input: type=0x%04x -> %s", rte_be_to_cpu_16(eth_type), next_node);
@@ -34,7 +34,7 @@ void gr_eth_input_add_type(rte_be16_t eth_type, const char *next_node) {
static uint16_t
eth_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
- uint16_t vlan_id, last_iface_id, last_vlan_id;
+ uint16_t vlan_id, last_iface_id, last_vlan_id, packets;
const struct iface *vlan_iface, *iface;
struct eth_input_mbuf_data *eth_in;
struct rte_ether_addr iface_mac;
@@ -45,11 +45,14 @@ eth_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, u
struct rte_mbuf *m;
size_t l2_hdr_size;
rte_edge_t edge;
+ uint64_t bytes;
iface = NULL;
vlan_iface = NULL;
- last_iface_id = UINT16_MAX;
+ last_iface_id = GR_IFACE_ID_UNDEF;
last_vlan_id = UINT16_MAX;
+ packets = 0;
+ bytes = 0;
for (uint16_t i = 0; i < nb_objs; i++) {
m = objs[i];
@@ -86,34 +89,38 @@ eth_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, u
eth_in->iface = vlan_iface;
}
- if (unlikely(rte_be_to_cpu_16(eth_type) < SNAP_MAX_LEN)) {
- edge = SNAP;
- goto snap;
- }
-
- edge = l2l3_edges[eth_type];
-
if (iface == NULL || iface->id != eth_in->iface->id) {
if (iface_get_eth_addr(eth_in->iface, &iface_mac) < 0) {
edge = INVALID_IFACE;
goto next;
}
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), iface->id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
iface = eth_in->iface;
- stats = iface_get_stats(rte_lcore_id(), eth_in->iface->id);
+ packets = 0;
+ bytes = 0;
}
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(m);
- stats->rx_packets += 1;
- stats->rx_bytes += rte_pktmbuf_pkt_len(m);
-
- if (unlikely(rte_is_multicast_ether_addr(ð->dst_addr))) {
- if (rte_is_broadcast_ether_addr(ð->dst_addr))
- eth_in->domain = ETH_DOMAIN_BROADCAST;
- else
- eth_in->domain = ETH_DOMAIN_MULTICAST;
- } else if (rte_is_same_ether_addr(ð->dst_addr, &iface_mac)) {
- eth_in->domain = ETH_DOMAIN_LOCAL;
+ if (unlikely(rte_be_to_cpu_16(eth_type) < SNAP_MAX_LEN)) {
+ edge = SNAP;
} else {
- eth_in->domain = ETH_DOMAIN_OTHER;
+ if (unlikely(rte_is_multicast_ether_addr(ð->dst_addr))) {
+ if (rte_is_broadcast_ether_addr(ð->dst_addr))
+ eth_in->domain = ETH_DOMAIN_BROADCAST;
+ else
+ eth_in->domain = ETH_DOMAIN_MULTICAST;
+ } else if (rte_is_same_ether_addr(ð->dst_addr, &iface_mac)) {
+ eth_in->domain = ETH_DOMAIN_LOCAL;
+ } else {
+ eth_in->domain = ETH_DOMAIN_OTHER;
+ }
+ rte_pktmbuf_adj(m, l2_hdr_size);
+ edge = l2l3_edges[eth_type];
}
next:
if (gr_mbuf_is_traced(m)
@@ -125,10 +132,15 @@ eth_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, u
t->vlan_id = vlan_id;
t->iface_id = eth_in->iface->id;
}
- rte_pktmbuf_adj(m, l2_hdr_size);
-snap:
rte_node_enqueue_x1(graph, node, edge, m);
}
+
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), iface->id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/infra/datapath/iface_output.c b/modules/infra/datapath/iface_output.c
index 169677644..256b6c456 100644
--- a/modules/infra/datapath/iface_output.c
+++ b/modules/infra/datapath/iface_output.c
@@ -16,14 +16,15 @@ enum {
NB_EDGES,
};
-static rte_edge_t iface_type_edges[GR_IFACE_TYPE_COUNT] = {INVAL};
+static rte_edge_t iface_type_edges[UINT_NUM_VALUES(gr_iface_type_t)] = {INVAL};
void iface_output_type_register(gr_iface_type_t type, const char *next_node) {
- LOG(DEBUG, "iface_output: iface_type=%s -> %s", gr_iface_type_name(type), next_node);
- if (type == GR_IFACE_TYPE_UNDEF || type >= ARRAY_DIM(iface_type_edges))
+ const char *type_name = gr_iface_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid iface type=%u", type);
if (iface_type_edges[type] != INVAL)
- ABORT("next node already registered for iface type=%s", gr_iface_type_name(type));
+ ABORT("next node already registered for iface type=%s", type_name);
+ LOG(DEBUG, "iface_output: iface_type=%s -> %s", type_name, next_node);
iface_type_edges[type] = gr_node_attach_parent("iface_output", next_node);
}
@@ -33,16 +34,22 @@ static uint16_t iface_output_process(
void **objs,
uint16_t nb_objs
) {
+ uint16_t last_iface_id, packets;
const struct iface *iface;
struct iface_stats *stats;
struct rte_mbuf *m;
rte_edge_t edge;
+ uint64_t bytes;
+
+ last_iface_id = GR_IFACE_ID_UNDEF;
+ packets = 0;
+ bytes = 0;
for (uint16_t i = 0; i < nb_objs; i++) {
m = objs[i];
iface = mbuf_data(m)->iface;
- if (iface == NULL || iface->type >= ARRAY_DIM(iface_type_edges)) {
+ if (iface == NULL) {
edge = INVAL;
goto next;
}
@@ -52,9 +59,18 @@ static uint16_t iface_output_process(
goto next;
}
- stats = iface_get_stats(rte_lcore_id(), iface->id);
- stats->tx_packets += 1;
- stats->tx_bytes += rte_pktmbuf_pkt_len(m);
+ if (iface->id != last_iface_id) {
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+ last_iface_id = iface->id;
+ packets = 0;
+ bytes = 0;
+ }
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(m);
edge = iface_type_edges[iface->type];
@@ -66,6 +82,12 @@ static uint16_t iface_output_process(
rte_node_enqueue_x1(graph, node, edge, m);
}
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/infra/datapath/loop_input.c b/modules/infra/datapath/loop_input.c
index 003b06439..5b92ac8cd 100644
--- a/modules/infra/datapath/loop_input.c
+++ b/modules/infra/datapath/loop_input.c
@@ -22,7 +22,7 @@ enum {
EDGE_COUNT,
};
-static rte_edge_t l3_edges[1 << 16] = {UNKNOWN_PROTO};
+static rte_edge_t l3_edges[UINT_NUM_VALUES(rte_be16_t)] = {UNKNOWN_PROTO};
void loopback_input_add_type(rte_be16_t eth_type, const char *next_node) {
LOG(DEBUG, "loopback_input: type=0x%04x -> %s", rte_be_to_cpu_16(eth_type), next_node);
diff --git a/modules/infra/datapath/loop_xvrf.c b/modules/infra/datapath/loop_xvrf.c
index 68c95bd92..6acf36648 100644
--- a/modules/infra/datapath/loop_xvrf.c
+++ b/modules/infra/datapath/loop_xvrf.c
@@ -28,9 +28,15 @@ static int trace_vrf_format(char *buf, size_t len, const void *data, size_t /*da
static uint16_t
loop_xvrf_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
struct eth_input_mbuf_data *eth_data;
+ uint16_t packets, last_iface_id;
struct iface_stats *stats;
struct rte_mbuf *m;
rte_edge_t edge;
+ uint64_t bytes;
+
+ last_iface_id = GR_IFACE_ID_UNDEF;
+ packets = 0;
+ bytes = 0;
for (uint16_t i = 0; i < nb_objs; i++) {
m = objs[i];
@@ -44,9 +50,18 @@ loop_xvrf_process(struct rte_graph *graph, struct rte_node *node, void **objs, u
eth_data->domain = ETH_DOMAIN_LOCAL;
// XXX: increment tx stats of gr-loopX on initial vrf
- stats = iface_get_stats(rte_lcore_id(), eth_data->iface->id);
- stats->rx_packets += 1;
- stats->rx_bytes += rte_pktmbuf_pkt_len(m);
+ if (last_iface_id != eth_data->iface->id) {
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+ last_iface_id = eth_data->iface->id;
+ packets = 0;
+ bytes = 0;
+ }
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(m);
if (gr_mbuf_is_traced(m) || (eth_data->iface->flags & GR_IFACE_F_PACKET_TRACE)) {
struct trace_vrf_data *t = gr_mbuf_trace_add(m, node, sizeof(*t));
@@ -55,6 +70,13 @@ loop_xvrf_process(struct rte_graph *graph, struct rte_node *node, void **objs, u
rte_node_enqueue_x1(graph, node, edge, m);
}
+
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/infra/datapath/main_loop.c b/modules/infra/datapath/main_loop.c
index 1c56676b1..8a9002950 100644
--- a/modules/infra/datapath/main_loop.c
+++ b/modules/infra/datapath/main_loop.c
@@ -250,9 +250,9 @@ void *gr_datapath_loop(void *priv) {
timestamp = rte_rdtsc();
for (;;) {
rte_graph_walk(graph);
- rte_rcu_qsbr_quiescent(rcu, rte_lcore_id());
if (++loop == HOUSEKEEPING_INTERVAL) {
+ rte_rcu_qsbr_quiescent(rcu, rte_lcore_id());
if (atomic_load(&w->shutdown) || atomic_load(&w->next_config) != cur) {
rte_rcu_qsbr_thread_offline(rcu, rte_lcore_id());
goto reconfig;
diff --git a/modules/infra/datapath/port_rx.c b/modules/infra/datapath/port_rx.c
index 21bd315e2..824e20c50 100644
--- a/modules/infra/datapath/port_rx.c
+++ b/modules/infra/datapath/port_rx.c
@@ -28,11 +28,15 @@ int rxtx_trace_format(char *buf, size_t len, const void *data, size_t /*data_len
return snprintf(buf, len, "port=%u queue=%u", t->port_id, t->queue_id);
}
-static rte_edge_t edges[GR_IFACE_MODE_COUNT] = {IFACE_MODE_UNKNOWN};
+static rte_edge_t edges[UINT_NUM_VALUES(gr_iface_mode_t)] = {IFACE_MODE_UNKNOWN};
void iface_input_mode_register(gr_iface_mode_t mode, const char *next_node) {
+ const char *mode_name = gr_iface_mode_name(mode);
+ if (strcmp(mode_name, "?") == 0)
+ ABORT("invalid iface mode=%u", mode);
if (edges[mode] != IFACE_MODE_UNKNOWN)
- ABORT("next node already registered for interface mode %u", mode);
+ ABORT("next node already registered for interface mode %s", mode_name);
+ LOG(DEBUG, "iface_input: mode=%s -> %s", mode_name, next_node);
edges[mode] = gr_node_attach_parent(RX_NODE_BASE, next_node);
}
@@ -42,7 +46,6 @@ rx_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t
const struct rx_node_ctx *ctx = rx_node_ctx(node);
const struct iface_info_port *port;
const struct rte_ether_hdr *eth;
- struct eth_input_mbuf_data *d;
const struct iface *iface;
uint16_t rx;
unsigned r;
@@ -66,14 +69,19 @@ rx_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t
return 0;
rx = rte_eth_rx_burst(ctx->rxq.port_id, ctx->rxq.queue_id, mbufs, ctx->burst_size);
- for (r = 0; r < rx; r++) {
- eth = rte_pktmbuf_mtod(mbufs[r], const struct rte_ether_hdr *);
- d = eth_input_mbuf_data(mbufs[r]);
- if (unlikely(eth->ether_type == RTE_BE16(RTE_ETHER_TYPE_SLOW)))
- d->iface = ctx->iface;
- else
- d->iface = iface;
- d->domain = ETH_DOMAIN_UNKNOWN;
+ if (rx == 0)
+ return 0;
+ if (ctx->iface->mode == GR_IFACE_MODE_BOND) {
+ for (r = 0; r < rx; r++) {
+ eth = rte_pktmbuf_mtod(mbufs[r], const struct rte_ether_hdr *);
+ if (unlikely(eth->ether_type == RTE_BE16(RTE_ETHER_TYPE_SLOW)))
+ mbuf_data(mbufs[r])->iface = ctx->iface;
+ else
+ mbuf_data(mbufs[r])->iface = iface;
+ }
+ } else {
+ for (r = 0; r < rx; r++)
+ mbuf_data(mbufs[r])->iface = iface;
}
if (unlikely(ctx->iface->flags & GR_IFACE_F_PACKET_TRACE)) {
diff --git a/modules/infra/datapath/xconnect.c b/modules/infra/datapath/xconnect.c
index 0126bd755..171d17a85 100644
--- a/modules/infra/datapath/xconnect.c
+++ b/modules/infra/datapath/xconnect.c
@@ -19,28 +19,57 @@ enum edges {
static uint16_t
xconnect_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
+ uint16_t last_rx_iface_id, last_tx_iface_id;
const struct iface_info_port *port;
const struct iface *iface, *peer;
+ uint16_t rx_packets, tx_packets;
+ uint64_t rx_bytes, tx_bytes;
+ struct iface_stats *stats;
struct rte_mbuf *mbuf;
rte_edge_t edge;
+ last_rx_iface_id = GR_IFACE_ID_UNDEF;
+ last_tx_iface_id = GR_IFACE_ID_UNDEF;
+ rx_packets = 0;
+ tx_packets = 0;
+ rx_bytes = 0;
+ tx_bytes = 0;
+
for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
iface = mbuf_data(mbuf)->iface;
peer = iface_from_id(iface->domain_id);
- struct iface_stats *rx_stats = iface_get_stats(rte_lcore_id(), iface->id);
- rx_stats->rx_packets++;
- rx_stats->rx_bytes += rte_pktmbuf_pkt_len(mbuf);
+ if (iface->id != last_rx_iface_id) {
+ if (rx_packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_rx_iface_id);
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ }
+ last_rx_iface_id = iface->id;
+ rx_packets = 0;
+ rx_bytes = 0;
+ }
+ rx_packets++;
+ rx_bytes += rte_pktmbuf_pkt_len(mbuf);
if (peer->type == GR_IFACE_TYPE_PORT) {
port = iface_info_port(peer);
mbuf->port = port->port_id;
edge = OUTPUT;
- struct iface_stats *tx_stats = iface_get_stats(rte_lcore_id(), peer->id);
- tx_stats->tx_packets++;
- tx_stats->tx_bytes += rte_pktmbuf_pkt_len(mbuf);
+ if (peer->id != last_tx_iface_id) {
+ if (tx_packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_tx_iface_id);
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ }
+ last_tx_iface_id = peer->id;
+ tx_packets = 0;
+ tx_bytes = 0;
+ }
+ tx_packets++;
+ tx_bytes += rte_pktmbuf_pkt_len(mbuf);
} else {
edge = NO_PORT;
}
@@ -51,6 +80,17 @@ xconnect_process(struct rte_graph *graph, struct rte_node *node, void **objs, ui
rte_node_enqueue_x1(graph, node, edge, mbuf);
}
+ if (rx_packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_rx_iface_id);
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ }
+ if (tx_packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_tx_iface_id);
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/ip/datapath/ip_input.c b/modules/ip/datapath/ip_input.c
index 57bbafbc7..cce8842b7 100644
--- a/modules/ip/datapath/ip_input.c
+++ b/modules/ip/datapath/ip_input.c
@@ -32,14 +32,15 @@ enum edges {
EDGE_COUNT,
};
-static rte_edge_t nh_type_edges[256] = {FORWARD};
+static rte_edge_t nh_type_edges[UINT_NUM_VALUES(gr_nh_type_t)] = {FORWARD};
void ip_input_register_nexthop_type(gr_nh_type_t type, const char *next_node) {
- LOG(DEBUG, "ip_input: nexthop type=%u -> %s", type, next_node);
- if (type == 0)
+ const char *type_name = gr_nh_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid nexthop type=%u", type);
if (nh_type_edges[type] != FORWARD)
- ABORT("next node already registered for nexthop type=%u", type);
+ ABORT("next node already registered for nexthop type=%s", type_name);
+ LOG(DEBUG, "ip_input: nh_type=%s -> %s", type_name, next_node);
nh_type_edges[type] = gr_node_attach_parent("ip_input", next_node);
}
diff --git a/modules/ip/datapath/ip_local.c b/modules/ip/datapath/ip_local.c
index e52a84846..4be3f1b4f 100644
--- a/modules/ip/datapath/ip_local.c
+++ b/modules/ip/datapath/ip_local.c
@@ -11,7 +11,7 @@
#include
#define UNKNOWN_PROTO 0
-static rte_edge_t edges[256] = {UNKNOWN_PROTO};
+static rte_edge_t edges[UINT_NUM_VALUES(uint8_t)] = {UNKNOWN_PROTO};
void ip_input_local_add_proto(uint8_t proto, const char *next_node) {
LOG(DEBUG, "ip_input_local: proto=%hhu -> %s", proto, next_node);
diff --git a/modules/ip/datapath/ip_output.c b/modules/ip/datapath/ip_output.c
index 0871eefd4..a505dd0bf 100644
--- a/modules/ip/datapath/ip_output.c
+++ b/modules/ip/datapath/ip_output.c
@@ -31,25 +31,27 @@ enum {
EDGE_COUNT,
};
-static rte_edge_t iface_type_edges[GR_IFACE_TYPE_COUNT] = {ETH_OUTPUT};
+static rte_edge_t iface_type_edges[UINT_NUM_VALUES(gr_iface_type_t)] = {ETH_OUTPUT};
void ip_output_register_interface_type(gr_iface_type_t type, const char *next_node) {
- LOG(DEBUG, "ip_output: iface_type=%u -> %s", type, next_node);
- if (type == GR_IFACE_TYPE_UNDEF || type >= ARRAY_DIM(iface_type_edges))
+ const char *type_name = gr_iface_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid iface type=%u", type);
if (iface_type_edges[type] != ETH_OUTPUT)
- ABORT("next node already registered for iface type=%u", type);
+ ABORT("next node already registered for iface type=%s", type_name);
+ LOG(DEBUG, "ip_output: iface_type=%s -> %s", type_name, next_node);
iface_type_edges[type] = gr_node_attach_parent("ip_output", next_node);
}
-static rte_edge_t nh_type_edges[256] = {ETH_OUTPUT};
+static rte_edge_t nh_type_edges[UINT_NUM_VALUES(gr_nh_type_t)] = {ETH_OUTPUT};
void ip_output_register_nexthop_type(gr_nh_type_t type, const char *next_node) {
- LOG(DEBUG, "ip_output: nexthop type=%u -> %s", type, next_node);
- if (type == 0)
+ const char *type_name = gr_nh_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid nexthop type=%u", type);
if (nh_type_edges[type] != ETH_OUTPUT)
- ABORT("next node already registered for nexthop type=%u", type);
+ ABORT("next node already registered for nexthop type=%s", type_name);
+ LOG(DEBUG, "ip_output: nh_type=%s -> %s", type_name, next_node);
nh_type_edges[type] = gr_node_attach_parent("ip_output", next_node);
}
diff --git a/modules/ip6/datapath/ip6_input.c b/modules/ip6/datapath/ip6_input.c
index e64f77385..a71318b75 100644
--- a/modules/ip6/datapath/ip6_input.c
+++ b/modules/ip6/datapath/ip6_input.c
@@ -30,14 +30,15 @@ enum edges {
EDGE_COUNT,
};
-static rte_edge_t nh_type_edges[256] = {FORWARD};
+static rte_edge_t nh_type_edges[UINT_NUM_VALUES(gr_nh_type_t)] = {FORWARD};
void ip6_input_register_nexthop_type(gr_nh_type_t type, const char *next_node) {
- LOG(DEBUG, "ip6_input: nexthop type=%u -> %s", type, next_node);
- if (type == 0)
+ const char *type_name = gr_nh_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid nexthop type=%u", type);
if (nh_type_edges[type] != FORWARD)
- ABORT("next node already registered for nexthop type=%u", type);
+ ABORT("next node already registered for nexthop type=%s", type_name);
+ LOG(DEBUG, "ip6_input: nh_type=%s -> %s", type_name, next_node);
nh_type_edges[type] = gr_node_attach_parent("ip6_input", next_node);
}
diff --git a/modules/ip6/datapath/ip6_local.c b/modules/ip6/datapath/ip6_local.c
index fed24c59d..14aabbbe3 100644
--- a/modules/ip6/datapath/ip6_local.c
+++ b/modules/ip6/datapath/ip6_local.c
@@ -17,7 +17,7 @@ enum {
ERROR,
EDGE_COUNT,
};
-static rte_edge_t edges[256] = {UNKNOWN_PROTO};
+static rte_edge_t edges[UINT_NUM_VALUES(uint8_t)] = {UNKNOWN_PROTO};
void ip6_input_local_add_proto(uint8_t proto, const char *next_node) {
LOG(DEBUG, "ip6_input_local: proto=%hhu -> %s", proto, next_node);
diff --git a/modules/ip6/datapath/ip6_output.c b/modules/ip6/datapath/ip6_output.c
index 6f335c7f5..58cea8119 100644
--- a/modules/ip6/datapath/ip6_output.c
+++ b/modules/ip6/datapath/ip6_output.c
@@ -25,25 +25,27 @@ enum {
EDGE_COUNT,
};
-static rte_edge_t iface_type_edges[GR_IFACE_TYPE_COUNT] = {ETH_OUTPUT};
+static rte_edge_t iface_type_edges[UINT_NUM_VALUES(gr_iface_type_t)] = {ETH_OUTPUT};
void ip6_output_register_interface_type(gr_iface_type_t type, const char *next_node) {
- LOG(DEBUG, "ip6_output: iface type=%u -> %s", type, next_node);
- if (type == GR_IFACE_TYPE_UNDEF || type >= ARRAY_DIM(iface_type_edges))
+ const char *type_name = gr_iface_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid iface type=%u", type);
if (iface_type_edges[type] != ETH_OUTPUT)
- ABORT("next node already registered for iface type=%u", type);
+ ABORT("next node already registered for iface type=%s", type_name);
+ LOG(DEBUG, "ip6_output: iface_type=%s -> %s", type_name, next_node);
iface_type_edges[type] = gr_node_attach_parent("ip6_output", next_node);
}
-static rte_edge_t nh_type_edges[256] = {ETH_OUTPUT};
+static rte_edge_t nh_type_edges[UINT_NUM_VALUES(gr_nh_type_t)] = {ETH_OUTPUT};
void ip6_output_register_nexthop_type(gr_nh_type_t type, const char *next_node) {
- LOG(DEBUG, "ip6_output: nexthop type=%u -> %s", type, next_node);
- if (type == 0)
+ const char *type_name = gr_nh_type_name(type);
+ if (strcmp(type_name, "?") == 0)
ABORT("invalid nexthop type=%u", type);
if (nh_type_edges[type] != ETH_OUTPUT)
- ABORT("next node already registered for nexthop type=%u", type);
+ ABORT("next node already registered for nexthop type=%s", type_name);
+ LOG(DEBUG, "ip6_output: nh_type=%s -> %s", type_name, next_node);
nh_type_edges[type] = gr_node_attach_parent("ip6_output", next_node);
}
diff --git a/modules/ipip/control.c b/modules/ipip/control.c
index fdfbf0ea4..b6defe3c8 100644
--- a/modules/ipip/control.c
+++ b/modules/ipip/control.c
@@ -113,9 +113,8 @@ static void ipip_to_api(void *info, const struct iface *iface) {
*api = ipip->base;
}
-static struct iface_type iface_type_ipip = {
+static const struct iface_type iface_type_ipip = {
.id = GR_IFACE_TYPE_IPIP,
- .name = "ipip",
.pub_size = sizeof(struct gr_iface_info_ipip),
.priv_size = sizeof(struct iface_info_ipip),
.init = iface_ipip_init,
diff --git a/modules/ipip/datapath_in.c b/modules/ipip/datapath_in.c
index 1e1b3552e..66f3599b5 100644
--- a/modules/ipip/datapath_in.c
+++ b/modules/ipip/datapath_in.c
@@ -37,15 +37,21 @@ ipip_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
struct ip_local_mbuf_data *ip_data;
ip4_addr_t last_src, last_dst;
struct iface_stats *stats;
+ uint16_t last_iface_id;
struct rte_mbuf *mbuf;
uint16_t last_vrf_id;
struct iface *ipip;
+ uint16_t packets;
rte_edge_t edge;
+ uint64_t bytes;
- ipip = NULL;
+ last_iface_id = GR_IFACE_ID_UNDEF;
+ last_vrf_id = GR_VRF_ID_ALL;
last_src = 0;
last_dst = 0;
- last_vrf_id = GR_VRF_ID_ALL;
+ packets = 0;
+ ipip = NULL;
+ bytes = 0;
for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
@@ -53,10 +59,19 @@ ipip_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
if (ip_data->dst != last_dst || ip_data->src != last_src
|| ip_data->vrf_id != last_vrf_id) {
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ packets = 0;
+ bytes = 0;
+ }
ipip = ipip_get_iface(ip_data->dst, ip_data->src, ip_data->vrf_id);
last_dst = ip_data->dst;
last_src = ip_data->src;
last_vrf_id = ip_data->vrf_id;
+ if (ipip != NULL)
+ last_iface_id = ipip->id;
}
if (ipip == NULL) {
edge = NO_TUNNEL;
@@ -73,9 +88,8 @@ ipip_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
eth_data->iface = ipip;
eth_data->domain = ETH_DOMAIN_LOCAL;
edge = IP_INPUT;
- stats = iface_get_stats(rte_lcore_id(), ipip->id);
- stats->rx_packets += 1;
- stats->rx_bytes += rte_pktmbuf_pkt_len(mbuf);
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(mbuf);
next:
if (gr_mbuf_is_traced(mbuf) || (ipip && ipip->flags & GR_IFACE_F_PACKET_TRACE)) {
struct trace_ipip_data *t = gr_mbuf_trace_add(mbuf, node, sizeof(*t));
@@ -84,6 +98,12 @@ ipip_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
rte_node_enqueue_x1(graph, node, edge, mbuf);
}
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/ipip/datapath_out.c b/modules/ipip/datapath_out.c
index 8db594e9e..c345be8c6 100644
--- a/modules/ipip/datapath_out.c
+++ b/modules/ipip/datapath_out.c
@@ -35,8 +35,16 @@ ipip_output_process(struct rte_graph *graph, struct rte_node *node, void **objs,
const struct rte_ipv4_hdr *inner;
struct rte_ipv4_hdr *outer;
const struct iface *iface;
+ struct iface_stats *stats;
+ uint16_t last_iface_id;
struct rte_mbuf *mbuf;
+ uint16_t packets;
rte_edge_t edge;
+ uint64_t bytes;
+
+ last_iface_id = GR_IFACE_ID_UNDEF;
+ packets = 0;
+ bytes = 0;
for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
@@ -74,9 +82,18 @@ ipip_output_process(struct rte_graph *graph, struct rte_node *node, void **objs,
}
ip_set_fields(outer, &tunnel);
- struct iface_stats *stats = iface_get_stats(rte_lcore_id(), iface->id);
- stats->tx_packets += 1;
- stats->tx_bytes += rte_pktmbuf_pkt_len(mbuf);
+ if (iface->id != last_iface_id) {
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+ last_iface_id = iface->id;
+ packets = 0;
+ bytes = 0;
+ }
+ packets += 1;
+ bytes += rte_pktmbuf_pkt_len(mbuf);
// Resolve nexthop for the encapsulated packet.
ip_data->nh = fib4_lookup(iface->vrf_id, ipip->remote);
@@ -86,6 +103,12 @@ ipip_output_process(struct rte_graph *graph, struct rte_node *node, void **objs,
rte_node_enqueue_x1(graph, node, edge, mbuf);
}
+ if (packets > 0) {
+ stats = iface_get_stats(rte_lcore_id(), last_iface_id);
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+
return nb_objs;
}
diff --git a/modules/l4/l4_input_local.c b/modules/l4/l4_input_local.c
index 0654eafc3..e8fe50a3d 100644
--- a/modules/l4/l4_input_local.c
+++ b/modules/l4/l4_input_local.c
@@ -20,7 +20,7 @@ enum edges {
EDGE_COUNT,
};
-static rte_edge_t udp_edges[65536] = {MANAGEMENT};
+static rte_edge_t udp_edges[UINT_NUM_VALUES(rte_be16_t)] = {MANAGEMENT};
void l4_input_register_port(uint8_t proto, rte_be16_t port, const char *next_node) {
uint16_t p = rte_be_to_cpu_16(port);