diff --git a/frr/zebra_dplane_grout.c b/frr/zebra_dplane_grout.c index 8f8b6e7b..7d166657 100644 --- a/frr/zebra_dplane_grout.c +++ b/frr/zebra_dplane_grout.c @@ -315,6 +315,8 @@ static const char *gr_req_type_to_str(uint32_t e) { return TOSTRING(GR_NH_ADD); case GR_NH_DEL: return TOSTRING(GR_NH_DEL); + case GR_INFRA_IFACE_GET: + return TOSTRING(GR_INFRA_IFACE_GET); case GR_INFRA_IFACE_LIST: return TOSTRING(GR_INFRA_IFACE_LIST); case GR_IP4_ADDR_LIST: @@ -327,6 +329,8 @@ static const char *gr_req_type_to_str(uint32_t e) { return TOSTRING(GR_IP4_ROUTE_LIST); case GR_IP6_ROUTE_LIST: return TOSTRING(GR_IP6_ROUTE_LIST); + case GR_SRV6_TUNSRC_SET: + return TOSTRING(GR_SRV6_TUNSRC_SET); default: return "unknown"; } diff --git a/modules/infra/api/gr_infra.h b/modules/infra/api/gr_infra.h index e1ea8892..51ca0fa7 100644 --- a/modules/infra/api/gr_infra.h +++ b/modules/infra/api/gr_infra.h @@ -240,6 +240,10 @@ struct gr_iface_stats { uint64_t tx_packets; uint64_t tx_bytes; uint64_t tx_errors; + uint64_t cp_rx_packets; + uint64_t cp_rx_bytes; + uint64_t cp_tx_packets; + uint64_t cp_tx_bytes; }; struct gr_infra_iface_stats_get_resp { diff --git a/modules/infra/api/stats.c b/modules/infra/api/stats.c index 1c6feb51..87433f33 100644 --- a/modules/infra/api/stats.c +++ b/modules/infra/api/stats.c @@ -266,6 +266,10 @@ static struct api_out iface_stats_get(const void * /*request*/, struct api_ctx * s.tx_packets = 0; s.tx_bytes = 0; s.tx_errors = 0; + s.cp_rx_packets = 0; + s.cp_rx_bytes = 0; + s.cp_tx_packets = 0; + s.cp_tx_bytes = 0; // Aggregate per-core stats for (int i = 0; i < RTE_MAX_LCORE; i++) { @@ -274,6 +278,10 @@ static struct api_out iface_stats_get(const void * /*request*/, struct api_ctx * s.rx_bytes += sw_stats->rx_bytes; s.tx_packets += sw_stats->tx_packets; s.tx_bytes += sw_stats->tx_bytes; + s.cp_rx_packets += sw_stats->cp_rx_packets; + s.cp_rx_bytes += sw_stats->cp_rx_bytes; + s.cp_tx_packets += sw_stats->cp_tx_packets; + s.cp_tx_bytes += sw_stats->cp_tx_bytes; } if (iface->type == GR_IFACE_TYPE_PORT) { @@ -386,17 +394,26 @@ telemetry_ifaces_info_get(const char * /*cmd*/, const char * /*params*/, struct // Software stats uint64_t rx_pkts = 0, rx_bytes = 0, tx_pkts = 0, tx_bytes = 0; + uint64_t cp_rx_pkts = 0, cp_rx_bytes = 0, cp_tx_pkts = 0, cp_tx_bytes = 0; for (int i = 0; i < RTE_MAX_LCORE; i++) { struct iface_stats *sw_stats = iface_get_stats(i, iface->id); rx_pkts += sw_stats->rx_packets; rx_bytes += sw_stats->rx_bytes; tx_pkts += sw_stats->tx_packets; tx_bytes += sw_stats->tx_bytes; + cp_rx_pkts += sw_stats->cp_rx_packets; + cp_rx_bytes += sw_stats->cp_rx_bytes; + cp_tx_pkts += sw_stats->cp_tx_packets; + cp_tx_bytes += sw_stats->cp_tx_bytes; } rte_tel_data_add_dict_uint(stats_container, "rx_packets", rx_pkts); rte_tel_data_add_dict_uint(stats_container, "rx_bytes", rx_bytes); rte_tel_data_add_dict_uint(stats_container, "tx_packets", tx_pkts); rte_tel_data_add_dict_uint(stats_container, "tx_bytes", tx_bytes); + rte_tel_data_add_dict_uint(stats_container, "cp_rx_packets", cp_rx_pkts); + rte_tel_data_add_dict_uint(stats_container, "cp_rx_bytes", cp_rx_bytes); + rte_tel_data_add_dict_uint(stats_container, "cp_tx_packets", cp_tx_pkts); + rte_tel_data_add_dict_uint(stats_container, "cp_tx_bytes", cp_tx_bytes); // Get hardware stats for physical ports. if (iface->type == GR_IFACE_TYPE_PORT) { diff --git a/modules/infra/cli/iface.c b/modules/infra/cli/iface.c index 8c6b7841..086a117f 100644 --- a/modules/infra/cli/iface.c +++ b/modules/infra/cli/iface.c @@ -324,6 +324,10 @@ static cmd_status_t iface_stats(struct gr_api_client *c, const struct ec_pnode * scols_table_new_column(table, "TX_PACKETS", 0, SCOLS_FL_RIGHT); scols_table_new_column(table, "TX_BYTES", 0, SCOLS_FL_RIGHT); scols_table_new_column(table, "TX_ERRORS", 0, SCOLS_FL_RIGHT); + scols_table_new_column(table, "CP_RX_PACKETS", 0, SCOLS_FL_RIGHT); + scols_table_new_column(table, "CP_RX_BYTES", 0, SCOLS_FL_RIGHT); + scols_table_new_column(table, "CP_TX_PACKETS", 0, SCOLS_FL_RIGHT); + scols_table_new_column(table, "CP_TX_BYTES", 0, SCOLS_FL_RIGHT); scols_table_set_column_separator(table, " "); for (uint16_t i = 0; i < resp->n_stats; i++) { @@ -346,6 +350,10 @@ static cmd_status_t iface_stats(struct gr_api_client *c, const struct ec_pnode * scols_line_sprintf(line, 4, "%lu", resp->stats[i].tx_packets); scols_line_sprintf(line, 5, "%lu", resp->stats[i].tx_bytes); scols_line_sprintf(line, 6, "%lu", resp->stats[i].tx_errors); + scols_line_sprintf(line, 7, "%lu", resp->stats[i].cp_rx_packets); + scols_line_sprintf(line, 8, "%lu", resp->stats[i].cp_rx_bytes); + scols_line_sprintf(line, 9, "%lu", resp->stats[i].cp_tx_packets); + scols_line_sprintf(line, 10, "%lu", resp->stats[i].cp_tx_bytes); } scols_print_table(table); diff --git a/modules/infra/control/gr_iface.h b/modules/infra/control/gr_iface.h index 891ae106..88bad955 100644 --- a/modules/infra/control/gr_iface.h +++ b/modules/infra/control/gr_iface.h @@ -92,6 +92,10 @@ struct __rte_cache_aligned iface_stats { uint64_t rx_bytes; uint64_t tx_packets; uint64_t tx_bytes; + uint64_t cp_rx_packets; + uint64_t cp_rx_bytes; + uint64_t cp_tx_packets; + uint64_t cp_tx_bytes; }; #define MAX_IFACES 1024 diff --git a/modules/infra/control/loopback.c b/modules/infra/control/loopback.c index daad1114..d7b62f7b 100644 --- a/modules/infra/control/loopback.c +++ b/modules/infra/control/loopback.c @@ -53,6 +53,7 @@ static void finalize_fd(struct event *ev, void * /*priv*/) { void loopback_tx(struct rte_mbuf *m) { struct mbuf_data *d = mbuf_data(m); struct iface_info_loopback *lo; + struct iface_stats *stats; struct iovec iov[2]; struct tun_pi pi; char *data; @@ -97,6 +98,10 @@ void loopback_tx(struct rte_mbuf *m) { LOG(ERR, "write to tun device failed %s", strerror(errno)); } + stats = iface_get_stats(rte_lcore_id(), d->iface->id); + stats->cp_tx_packets += 1; + stats->cp_tx_bytes += rte_pktmbuf_pkt_len(m); + end: if (!rte_pktmbuf_is_contiguous(m)) rte_free(data); @@ -104,9 +109,10 @@ void loopback_tx(struct rte_mbuf *m) { } static void iface_loopback_poll(evutil_socket_t, short reason, void *ev_iface) { - struct eth_input_mbuf_data *e; - struct iface_info_loopback *lo; struct iface *iface = ev_iface; + struct iface_info_loopback *lo; + struct eth_input_mbuf_data *e; + struct iface_stats *stats; struct rte_mbuf *mbuf; size_t read_len; size_t len; @@ -155,6 +161,10 @@ static void iface_loopback_poll(evutil_socket_t, short reason, void *ev_iface) { e->iface = iface; e->domain = ETH_DOMAIN_LOOPBACK; + stats = iface_get_stats(rte_lcore_id(), iface->id); + stats->cp_rx_packets += 1; + stats->cp_rx_bytes += rte_pktmbuf_pkt_len(mbuf); + post_to_stack(loopback_get_control_id(), mbuf); return; diff --git a/modules/infra/control/netlink.c b/modules/infra/control/netlink.c index 4409104c..b4914a60 100644 --- a/modules/infra/control/netlink.c +++ b/modules/infra/control/netlink.c @@ -231,7 +231,16 @@ static int netlink_add_del_addr(const char *ifname, const void *addr, size_t add ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa)); ifa->ifa_family = is_ipv4 ? AF_INET : AF_INET6; - ifa->ifa_prefixlen = is_ipv4 ? 32 : 128; + if (is_ipv4) { + ifa->ifa_prefixlen = 32; + } else { + // For Link local address, a /64 is required + // to reach other nodes on the link + if (rte_ipv6_addr_is_linklocal(addr)) + ifa->ifa_prefixlen = 64; + else + ifa->ifa_prefixlen = 128; + } ifa->ifa_scope = RT_SCOPE_UNIVERSE; ifa->ifa_index = ifindex; diff --git a/modules/ip6/control/address.c b/modules/ip6/control/address.c index c42ef107..170641cd 100644 --- a/modules/ip6/control/address.c +++ b/modules/ip6/control/address.c @@ -403,6 +403,8 @@ static void ip6_iface_event_handler(uint32_t event, const void *obj) { switch (event) { case GR_EVENT_IFACE_POST_ADD: if (iface_get_eth_addr(iface->id, &mac) == 0) { + // Modify the mac address to match a Modified EUI-64 + mac.addr_bytes[0] ^= 0x02; rte_ipv6_llocal_from_ethernet(&link_local, &mac); if (iface6_addr_add(iface, &link_local, 64) < 0) errno_log(errno, "iface_addr_add"); diff --git a/modules/ip6/control/nexthop.c b/modules/ip6/control/nexthop.c index 17e06bbf..6ac477af 100644 --- a/modules/ip6/control/nexthop.c +++ b/modules/ip6/control/nexthop.c @@ -222,6 +222,9 @@ void ndp_probe_input_cb(struct rte_mbuf *m) { } // Flush all held packets. + if (l3 == NULL) + goto free; + struct rte_mbuf *held = l3->held_pkts_head; while (held != NULL) { struct ip6_output_mbuf_data *o;