Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions frr/zebra_dplane_grout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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";
}
Expand Down
4 changes: 4 additions & 0 deletions modules/infra/api/gr_infra.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
17 changes: 17 additions & 0 deletions modules/infra/api/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions modules/infra/cli/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions modules/infra/control/gr_iface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 12 additions & 2 deletions modules/infra/control/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -97,16 +98,21 @@ 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);
rte_pktmbuf_free(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;
Expand Down Expand Up @@ -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;

Expand Down
11 changes: 10 additions & 1 deletion modules/infra/control/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions modules/ip6/control/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment on lines +406 to +407
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should fix this in DPDK?

Copy link
Member

@david-marchand david-marchand Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPDK states compliance against RFC 2464.

/*                                                                                                  
 * Generate a link-local IPv6 address from an Ethernet address as specified in                      
 * RFC 2464, section 5.                                                                             
 *                                                                                                  
 * @param[out] ip                                                                                   
 *   The link-local IPv6 address to generate.                                                       
 * @param[in] mac                                                                                   
 *   An Ethernet address.                                                                           
 */                                                                                                 
static inline void                                                                                  
rte_ipv6_llocal_from_ethernet(struct rte_ipv6_addr *ip, const struct rte_ether_addr *mac)       

Section 5 points at section 4 of this RFC and reads like:

   The Interface Identifier is then formed from the EUI-64 by
   complementing the "Universal/Local" (U/L) bit, which is the next-to-
   lowest order bit of the first octet of the EUI-64.  Complementing
   this bit will generally change a 0 value to a 1, since an interface's
   built-in address is expected to be from a universally administered
   address space and hence have a globally unique value.  A universally
   administered IEEE 802 address or an EUI-64 is signified by a 0 in the
   U/L bit position, while a globally unique IPv6 Interface Identifier
   is signified by a 1 in the corresponding position.  For further
   discussion on this point, see [[AARCH](https://datatracker.ietf.org/doc/html/rfc2464#ref-AARCH)].

The reference AARCH is a link to the discussion on IPv6 address architecture, which is current RFC 4291.

So it indeed seems like DPDK should be fixed.

rte_ipv6_llocal_from_ethernet(&link_local, &mac);
if (iface6_addr_add(iface, &link_local, 64) < 0)
errno_log(errno, "iface_addr_add");
Expand Down
3 changes: 3 additions & 0 deletions modules/ip6/control/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down