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);