Skip to content
Draft
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
758 changes: 412 additions & 346 deletions docs/graph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 70 additions & 3 deletions frr/if_grout.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,39 @@ static uint64_t gr_if_flags_to_netlink(struct gr_iface *gr_if, enum zebra_link_t
return frr_if_flags;
}

static ifindex_t gr_bridge_id_to_if_index(uint16_t domain_id) {
struct gr_l2_bridge_get_req req = {.bridge_id = domain_id};
struct gr_l2_bridge *bridge_info = NULL;
ifindex_t idx = IFINDEX_INTERNAL;
void *resp_ptr;

if (grout_client_send_recv(GR_L2_BRIDGE_GET, sizeof(req), &req, &resp_ptr) < 0) {
gr_log_err("error requesting bridge_info with id %u", domain_id);
goto cleanup;
}
bridge_info = resp_ptr;
if (bridge_info->iface_id == 0) {
printf("No bridge interface for domain %u\n", domain_id);
goto cleanup;
}
idx = ifindex_grout_to_frr(bridge_info->iface_id);
cleanup:
free(bridge_info);
return idx;
}

void grout_link_change(struct gr_iface *gr_if, bool new, bool startup) {
enum zebra_slave_iftype slave_type = ZEBRA_IF_SLAVE_NONE;
enum zebra_link_type link_type = ZEBRA_LLT_UNKNOWN;
enum zebra_iftype zif_type = ZEBRA_IF_OTHER;
const struct gr_iface_info_vlan *gr_vlan = NULL;
const struct gr_iface_info_port *gr_port = NULL;
const struct gr_iface_info_bond *gr_bond = NULL;
const struct gr_iface_info_bridge *gr_bridge = NULL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t master_ifindex = IFINDEX_INTERNAL;
const struct rte_ether_addr *mac = NULL;
struct zebra_dplane_ctx *ctx;
uint32_t txqlen = 1000;
Expand Down Expand Up @@ -85,6 +109,13 @@ void grout_link_change(struct gr_iface *gr_if, bool new, bool startup) {
link_type = ZEBRA_LLT_ETHER;
zif_type = ZEBRA_IF_VRF;
break;
case GR_IFACE_TYPE_BRIDGE:
gr_bridge = (struct gr_iface_info_bridge *)&gr_if->info;
link_type = ZEBRA_LLT_ETHER;
zif_type = ZEBRA_IF_BRIDGE;
mac = &gr_bridge->base.mac;
// bridge_ifindex = ifindex_grout_to_frr(gr_if->id);
break;
case GR_IFACE_TYPE_UNDEF:
default:
gr_log_err(
Expand All @@ -95,6 +126,13 @@ void grout_link_change(struct gr_iface *gr_if, bool new, bool startup) {
return;
}

if (gr_if->mode == GR_IFACE_MODE_L2_BRIDGE) {
master_ifindex = gr_bridge_id_to_if_index(gr_if->domain_id);
if (master_ifindex == IFINDEX_INTERNAL)
return;
slave_type = ZEBRA_IF_SLAVE_BRIDGE;
}

ctx = dplane_ctx_alloc();
dplane_ctx_set_ns_id(ctx, GROUT_NS);
dplane_ctx_set_ifp_link_nsid(ctx, GROUT_NS);
Expand All @@ -111,9 +149,8 @@ void grout_link_change(struct gr_iface *gr_if, bool new, bool startup) {
dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_QUEUED);
dplane_ctx_set_ifp_mtu(ctx, gr_if->base.mtu);

// no bridge support in grout
dplane_ctx_set_ifp_bridge_ifindex(ctx, IFINDEX_INTERNAL);
dplane_ctx_set_ifp_master_ifindex(ctx, IFINDEX_INTERNAL);
dplane_ctx_set_ifp_bridge_ifindex(ctx, bridge_ifindex);
dplane_ctx_set_ifp_master_ifindex(ctx, master_ifindex);
dplane_ctx_set_ifp_bond_ifindex(ctx, bond_ifindex);
dplane_ctx_set_ifp_zif_slave_type(ctx, slave_type);
dplane_ctx_set_ifp_bypass(ctx, 0);
Expand Down Expand Up @@ -292,3 +329,33 @@ enum zebra_dplane_result grout_set_sr_tunsrc(struct zebra_dplane_ctx *ctx) {

return ZEBRA_DPLANE_REQUEST_SUCCESS;
}

void grout_bridge_mac_change(bool new, const struct gr_l2_mac_entry *entry) {
struct zebra_dplane_ctx *ctx = dplane_ctx_alloc();
struct in_addr vtep_ip = {0};
struct ethaddr mac;

memcpy(&mac, entry->mac.addr_bytes, sizeof(mac));

dplane_ctx_set_op(ctx, new ? DPLANE_OP_NEIGH_INSTALL : DPLANE_OP_NEIGH_DELETE);
dplane_ctx_set_ns_id(ctx, GROUT_NS);
dplane_ctx_set_ifindex(ctx, ifindex_grout_to_frr(entry->iface_id));
dplane_ctx_mac_set_addr(ctx, &mac);
dplane_ctx_mac_set_nhg_id(ctx, 0);
dplane_ctx_mac_set_ndm_state(ctx, 0);
dplane_ctx_mac_set_ndm_flags(ctx, 0);
dplane_ctx_mac_set_dst_present(ctx, false);
dplane_ctx_mac_set_vtep_ip(ctx, &vtep_ip);
dplane_ctx_mac_set_vid(ctx, 0);
dplane_ctx_mac_set_dp_static(ctx, entry->age == 0);
dplane_ctx_mac_set_local_inactive(ctx, false);
dplane_ctx_mac_set_vni(ctx, 0);
dplane_ctx_mac_set_is_sticky(ctx, false);
dplane_provider_enqueue_to_zebra(ctx);
zlog_debug(
"grout_bridge_mac_change %s bridge %u iface %u mac",
new ? "add" : "del",
entry->bridge_id,
entry->iface_id
);
}
2 changes: 2 additions & 0 deletions frr/if_grout.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <gr_infra.h>
#include <gr_ip4.h>
#include <gr_ip6.h>
#include <gr_l2.h>
#include <gr_nexthop.h>

#include <stdbool.h>
Expand All @@ -17,3 +18,4 @@ enum zebra_dplane_result grout_set_sr_tunsrc(struct zebra_dplane_ctx *ctx);
void grout_interface_addr4_change(bool new, const struct gr_ip4_ifaddr *ifa);
void grout_interface_addr6_change(bool new, const struct gr_ip6_ifaddr *ifa);
void grout_link_change(struct gr_iface *gr_if, bool new, bool startup);
void grout_bridge_mac_change(bool new, const struct gr_l2_mac_entry *entry);
16 changes: 16 additions & 0 deletions frr/zebra_dplane_grout.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ static void dplane_grout_connect(struct event *) {
{.type = GR_EVENT_IP6_ADDR_ADD, .suppress_self_events = false},
{.type = GR_EVENT_IP_ADDR_DEL, .suppress_self_events = false},
{.type = GR_EVENT_IP6_ADDR_DEL, .suppress_self_events = false},
{.type = GR_EVENT_BRIDGE_MAC_ADD, .suppress_self_events = false},
{.type = GR_EVENT_BRIDGE_MAC_DEL, .suppress_self_events = false},
};

if (grout_notif_subscribe(&grout_ctx.dplane_notifs, gr_evts, ARRAY_SIZE(gr_evts)) < 0)
Expand Down Expand Up @@ -333,6 +335,8 @@ static const char *gr_req_type_to_str(uint32_t e) {
return TOSTRING(GR_IP6_ROUTE_LIST);
case GR_SRV6_TUNSRC_SET:
return TOSTRING(GR_SRV6_TUNSRC_SET);
case GR_L2_BRIDGE_GET:
return TOSTRING(GR_L2_BRIDGE_GET);
default:
return "unknown";
}
Expand Down Expand Up @@ -413,6 +417,10 @@ static const char *gr_evt_to_str(uint32_t e) {
return TOSTRING(GR_EVENT_NEXTHOP_UPDATE);
case GR_EVENT_NEXTHOP_DELETE:
return TOSTRING(GR_EVENT_NEXTHOP_DELETE);
case GR_EVENT_BRIDGE_MAC_ADD:
return TOSTRING(GR_EVENT_BRIDGE_MAC_ADD);
case GR_EVENT_BRIDGE_MAC_DEL:
return TOSTRING(GR_EVENT_BRIDGE_MAC_DEL);
default:
return "unknown";
}
Expand All @@ -421,6 +429,7 @@ static const char *gr_evt_to_str(uint32_t e) {
static void dplane_read_notifications(struct event *event) {
struct event_loop *dg_master = dplane_get_thread_master();
struct gr_api_event *gr_e = NULL;
struct gr_l2_mac_entry *mac_entry;
struct gr_ip4_ifaddr *ifa4;
struct gr_ip6_ifaddr *ifa6;
struct gr_iface *iface;
Expand Down Expand Up @@ -481,6 +490,13 @@ static void dplane_read_notifications(struct event *event) {
);
grout_interface_addr6_change(new, ifa6);
break;
case GR_EVENT_BRIDGE_MAC_ADD:
new = true;
// fallthrough
case GR_EVENT_BRIDGE_MAC_DEL:
mac_entry = PAYLOAD(gr_e);
grout_bridge_mac_change(new, mac_entry);
break;
default:
gr_log_debug(
"Unknown notification %s (0x%x) received",
Expand Down
12 changes: 8 additions & 4 deletions modules/infra/api/gr_infra.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef enum : uint8_t {
GR_IFACE_TYPE_VLAN,
GR_IFACE_TYPE_IPIP,
GR_IFACE_TYPE_BOND,
GR_IFACE_TYPE_BRIDGE,
GR_IFACE_TYPE_COUNT
} gr_iface_type_t;

Expand Down Expand Up @@ -55,6 +56,7 @@ typedef enum : uint16_t {
typedef enum : uint8_t {
GR_IFACE_MODE_L3 = 0,
GR_IFACE_MODE_L1_XC,
GR_IFACE_MODE_L2_BRIDGE,
GR_IFACE_MODE_COUNT
} gr_iface_mode_t;

Expand All @@ -66,10 +68,8 @@ struct __gr_iface_base {
gr_iface_flags_t flags; // Interface flags. Bit mask of GR_IFACE_F_*.
gr_iface_state_t state; // Interface state. Bit mask of GR_IFACE_S_*.
uint16_t mtu; // Maximum transmission unit size (incl. headers).
union {
uint16_t vrf_id; // L3 addressing and routing domain
uint16_t domain_id; // L2 xconnect peer interface id
};
uint16_t vrf_id; // L3 addressing and routing domain
uint16_t domain_id; // L2 xconnect peer interface id
uint32_t speed; //!< Link speed in Megabit/sec.
};

Expand Down Expand Up @@ -400,6 +400,8 @@ static inline const char *gr_iface_type_name(gr_iface_type_t type) {
return "ipip";
case GR_IFACE_TYPE_BOND:
return "bond";
case GR_IFACE_TYPE_BRIDGE:
return "bridge";
case GR_IFACE_TYPE_COUNT:
break;
}
Expand All @@ -413,6 +415,8 @@ static inline const char *gr_iface_mode_name(gr_iface_mode_t mode) {
return "l3";
case GR_IFACE_MODE_L1_XC:
return "l1-xc";
case GR_IFACE_MODE_L2_BRIDGE:
return "l2-bridge";
case GR_IFACE_MODE_COUNT:
break;
}
Expand Down
12 changes: 9 additions & 3 deletions modules/infra/cli/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,18 +256,24 @@ static cmd_status_t iface_list(struct gr_api_client *c, const struct ec_pnode *p
switch (iface->mode) {
case GR_IFACE_MODE_L1_XC:
scols_line_set_data(line, 3, "XC");
scols_line_set_data(line, 4, "");
break;
case GR_IFACE_MODE_L3:
scols_line_set_data(line, 3, "L3");
// VRF
scols_line_sprintf(line, 4, "vrf: %u", iface->vrf_id);
break;
case GR_IFACE_MODE_L2_BRIDGE:
scols_line_set_data(line, 3, "L2");
// Bridge domain
scols_line_sprintf(line, 4, "br: %u", iface->domain_id);
break;
default:
scols_line_sprintf(line, 3, "%u", iface->mode);
scols_line_set_data(line, 4, "");
break;
}

// vrf
scols_line_sprintf(line, 4, "%u", iface->vrf_id);

// type
scols_line_sprintf(line, 5, "%s", gr_iface_type_name(iface->type));

Expand Down
11 changes: 10 additions & 1 deletion modules/infra/control/ctlplane.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static struct rte_mempool *cp_pool;
static struct event_base *ev_base;

static control_input_t port_output_id;
static control_input_t bridge_output_id;

static void finalize_fd(struct event *ev, void * /*priv*/) {
int fd = event_get_fd(ev);
Expand Down Expand Up @@ -108,10 +109,13 @@ static void iface_cp_poll(evutil_socket_t, short reason, void *ev_iface) {
struct rte_vlan_hdr *vlan;
struct rte_mbuf *mbuf;
rte_be16_t ether_type;
control_input_t node;
size_t read_len;
size_t len;
char *data;

node = port_output_id;

if (reason & EV_CLOSED) {
LOG(ERR, "tap device %s deleted", iface->name);
iface_destroy(iface->id);
Expand Down Expand Up @@ -227,7 +231,10 @@ static void iface_cp_poll(evutil_socket_t, short reason, void *ev_iface) {
goto err;
}
iface = child_iface;
} else if (iface->type == GR_IFACE_TYPE_BRIDGE) {
node = bridge_output_id;
}

mbuf_data(mbuf)->iface = iface;

stats = iface_get_stats(rte_lcore_id(), iface->id);
Expand All @@ -237,7 +244,7 @@ static void iface_cp_poll(evutil_socket_t, short reason, void *ev_iface) {
if (gr_config.log_packets)
trace_log_packet(mbuf, "cp rx", iface->name);

post_to_stack(port_output_id, mbuf);
post_to_stack(node, mbuf);
return;

err:
Expand Down Expand Up @@ -423,6 +430,7 @@ static void iface_event(uint32_t event, const void *obj) {
case GR_IFACE_TYPE_PORT:
case GR_IFACE_TYPE_VLAN:
case GR_IFACE_TYPE_BOND:
case GR_IFACE_TYPE_BRIDGE:
break;
default:
return;
Expand Down Expand Up @@ -468,6 +476,7 @@ static void cp_module_init(struct event_base *base) {
ABORT("pktmbuf_pool returned NULL");
ev_base = base;
port_output_id = gr_control_input_register_handler("port_output", true);
bridge_output_id = gr_control_input_register_handler("l2_bridge", true);
}

static void cp_module_fini(struct event_base *) {
Expand Down
Loading
Loading