diff --git a/ldpd/interface.c b/ldpd/interface.c index f0e70cbacce1..7208548e290a 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -8,6 +8,7 @@ */ #include +#include "privs.h" #include "ldpd.h" #include "ldpe.h" @@ -16,6 +17,8 @@ #include "sockopt.h" +extern struct zebra_privs_t ldpe_privs; + static __inline int iface_compare(const struct iface *, const struct iface *); static struct if_addr *if_addr_new(struct kaddr *); static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *); @@ -93,6 +96,20 @@ ldpe_if_init(struct iface *iface) ldp_sync_fsm_init(iface, LDP_SYNC_STA_NOT_ACH); } +/* proc sys net mpls conf input set to 1 or 0 + * should be used from ldpe only + */ +void ldpe_interface_set_mpls(struct iface *iface, bool val) +{ + struct ldp_igp_configure_if_mpls config; + + config.ifindex = iface->ifindex; + config.status = val; + + ldpe_imsg_compose_parent(IMSG_LDP_CONFIGURE_IF_MPLS, getpid(), &config, + sizeof(config)); +} + void ldpe_if_exit(struct iface *iface) { @@ -277,6 +294,7 @@ if_start(struct iface *iface, int af) log_debug("%s: %s address-family %s", __func__, iface->name, af_name(af)); + ldpe_interface_set_mpls(iface, true); ia = iface_af_get(iface, af); gettimeofday(&now, NULL); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index df682a1347be..8d2ca9f38546 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -124,6 +124,15 @@ ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *state) return 0; } +int ldp_sync_zebra_send_configure_if_mpls(struct ldp_igp_configure_if_mpls *config) +{ + if (zebra_send_interface_mpls_set(zclient, VRF_DEFAULT, config->ifindex, + config->status) <= 0) + return -1; + + return zclient_send_message(zclient); +} + static int ldp_sync_zebra_send_announce(void) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 3c616d4a8c8b..6e37bfe34157 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -602,6 +602,15 @@ static void main_dispatch_ldpe(struct event *thread) ldp_sync_zebra_send_state_update((struct ldp_igp_sync_if_state *)imsg.data); break; + case IMSG_LDP_CONFIGURE_IF_MPLS: + if (imsg.hdr.len != + IMSG_HEADER_SIZE + + sizeof(struct ldp_igp_configure_if_mpls)) + fatalx("IMSG_LDP_CONFIGURE_IF_MPLS imsg with wrong len"); + + ldp_sync_zebra_send_configure_if_mpls( + (struct ldp_igp_configure_if_mpls *)imsg.data); + break; default: log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); @@ -1519,6 +1528,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) if (if_lookup_name(xconf, iface->name) == NULL) { switch (ldpd_process) { case PROC_LDP_ENGINE: + ldpe_interface_set_mpls(iface, false); ldpe_if_exit(iface); break; case PROC_LDE_ENGINE: diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 81c6ba3ccd57..33466293bdfb 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -151,6 +151,7 @@ enum imsg_type { IMSG_RLFA_UNREG_ALL, IMSG_RLFA_LABELS, IMSG_AGENTX_ENABLED, + IMSG_LDP_CONFIGURE_IF_MPLS, }; struct ldpd_init { @@ -890,6 +891,7 @@ extern char ctl_sock_path[MAXPATHLEN]; void ldp_zebra_init(struct event_loop *m); void ldp_zebra_destroy(void); int ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *); +int ldp_sync_zebra_send_configure_if_mpls(struct ldp_igp_configure_if_mpls *); int ldp_zebra_send_rlfa_labels(struct zapi_rlfa_response * rlfa_labels); diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index f310ba5dd209..7ba26de193db 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -306,6 +306,7 @@ void ldpe_l2vpn_init(struct l2vpn *); void ldpe_l2vpn_exit(struct l2vpn *); void ldpe_l2vpn_pw_init(struct l2vpn_pw *); void ldpe_l2vpn_pw_exit(struct l2vpn_pw *); +extern void ldpe_interface_set_mpls(struct iface *iface, bool val); DECLARE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state)); diff --git a/lib/ldp_sync.h b/lib/ldp_sync.h index 3a6ae5b3575a..85adb0870d32 100644 --- a/lib/ldp_sync.h +++ b/lib/ldp_sync.h @@ -56,6 +56,11 @@ struct ldp_igp_sync_if_state { bool sync_start; }; +struct ldp_igp_configure_if_mpls { + ifindex_t ifindex; + bool status; +}; + struct ldp_igp_sync_if_state_req { int proto; ifindex_t ifindex; diff --git a/lib/zclient.c b/lib/zclient.c index 1b2ff02f6137..4e582c773d22 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2864,6 +2864,52 @@ size_t zebra_interface_link_params_write(struct stream *s, return w; } +int zebra_send_interface_mpls_set(struct zclient *zclient, vrf_id_t vrf_id, + ifindex_t ifindex, bool set) +{ + struct stream *s; + int w; + + if (!zclient->obuf) + return 0; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_INTERFACE_MPLS_SET, VRF_DEFAULT); + + w = stream_putl(s, ifindex); + w += stream_putc(s, set); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + +struct interface *zebra_interface_mpls_set_read(struct stream *s, + vrf_id_t vrf_id, + bool *value_to_set) +{ + ifindex_t ifindex; + struct interface *ifp = NULL; + + STREAM_GETL(s, ifindex); + + ifp = if_lookup_by_index(ifindex, vrf_id); + + if (ifp == NULL) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: unknown ifindex %u, shouldn't happen", __func__, + ifindex); + return NULL; + } + if (value_to_set) + STREAM_GETC(s, *value_to_set); + +stream_failure: + return ifp; +} + /* * format of message for address addition is: * 0 diff --git a/lib/zclient.h b/lib/zclient.h index 8b6aebc2fda8..43fa1a893376 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -133,6 +133,7 @@ typedef enum { ZEBRA_INTERFACE_DISABLE_RADV, ZEBRA_NEXTHOP_LOOKUP_MRIB, ZEBRA_INTERFACE_LINK_PARAMS, + ZEBRA_INTERFACE_MPLS_SET, ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_DELETE, ZEBRA_MPLS_LABELS_REPLACE, @@ -1053,6 +1054,12 @@ extern struct interface *zebra_interface_link_params_read(struct stream *s, bool *changed); extern size_t zebra_interface_link_params_write(struct stream *, struct interface *); +extern int zebra_send_interface_mpls_set(struct zclient *zclient, + vrf_id_t vrf_id, ifindex_t ifindex, + bool set); +extern struct interface *zebra_interface_mpls_set_read(struct stream *s, + vrf_id_t vrf_id, + bool *value_to_set); extern enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t chunk_size, uint32_t base); diff --git a/tests/topotests/ldp_topo1/r1/zebra.conf b/tests/topotests/ldp_topo1/r1/zebra.conf index 55b4b0e9c656..877b93810347 100644 --- a/tests/topotests/ldp_topo1/r1/zebra.conf +++ b/tests/topotests/ldp_topo1/r1/zebra.conf @@ -9,6 +9,7 @@ interface r1-eth0 description to sw0 ip address 10.0.1.1/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r2/zebra.conf b/tests/topotests/ldp_topo1/r2/zebra.conf index dd1dbac32b8a..688aece30e03 100644 --- a/tests/topotests/ldp_topo1/r2/zebra.conf +++ b/tests/topotests/ldp_topo1/r2/zebra.conf @@ -9,16 +9,19 @@ interface r2-eth0 description to sw0 ip address 10.0.1.2/24 no link-detect + mpls auto ! interface r2-eth1 description to sw1 ip address 10.0.2.2/24 no link-detect + mpls auto ! interface r2-eth2 description to sw2 ip address 10.0.3.2/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r3/zebra.conf b/tests/topotests/ldp_topo1/r3/zebra.conf index 456820fdb48a..dd76f9ea1468 100644 --- a/tests/topotests/ldp_topo1/r3/zebra.conf +++ b/tests/topotests/ldp_topo1/r3/zebra.conf @@ -9,11 +9,13 @@ interface r3-eth0 description to sw1 ip address 10.0.2.3/24 no link-detect + mpls auto ! interface r3-eth1 description to sw2 ip address 10.0.3.3/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r4/zebra.conf b/tests/topotests/ldp_topo1/r4/zebra.conf index 4a270af578f6..149dc19b52b3 100644 --- a/tests/topotests/ldp_topo1/r4/zebra.conf +++ b/tests/topotests/ldp_topo1/r4/zebra.conf @@ -9,6 +9,7 @@ interface r4-eth0 description to sw1 ip address 10.0.2.4/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py index fdd75581a3ec..eba2be424054 100644 --- a/tests/topotests/ldp_topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py @@ -134,6 +134,7 @@ def setup_module(module): tgen.start_topology() net = tgen.net + os.environ["TOPOTESTS_MPLS_AUTO"] = "1" # Starting Routers for i in range(1, 5): @@ -781,6 +782,37 @@ def test_linux_mpls_routes(): assert fatal_error == "", fatal_error +def _check_mpls_interface_set(rname, ifname, value): + tgen = get_topogen() + val = ( + tgen.net[rname] + .cmd_raises("sysctl -n " + "net.mpls.conf." + ifname + ".input") + .strip() + ) + assert ( + val == value + ), f"{rname}, interface {ifname} has MPLS flag set to {val}, unexpected" + + +def test_linux_mpls_interface_settings(): + global fatal_error + + # Skip if previous fatal error condition is raised + if fatal_error != "": + pytest.skip(fatal_error) + + # Verify Linux Kernel MPLS settings + print("\n\n** Verifying Linux MPLS interface settings") + print("******************************************\n") + _check_mpls_interface_set("r1", "r1-eth0", "1") + _check_mpls_interface_set("r2", "r2-eth0", "1") + _check_mpls_interface_set("r2", "r2-eth1", "1") + _check_mpls_interface_set("r2", "r2-eth2", "1") + _check_mpls_interface_set("r3", "r3-eth0", "1") + _check_mpls_interface_set("r3", "r3-eth1", "1") + _check_mpls_interface_set("r4", "r4-eth0", "1") + + def test_shutdown_check_stderr(): global fatal_error net = get_topogen().net diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 7b06f3d127ed..ba5b4cccbd44 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -896,9 +896,13 @@ def start(self): daemon=daemon, ) + if nrouter.daemons["ldpd"] == 1 and not os.environ.get("TOPOTESTS_MPLS_AUTO"): + need_mpls_for_ldp = True + else: + need_mpls_for_ldp = False if result != "": self.tgen.set_error(result) - elif nrouter.daemons["ldpd"] == 1 or nrouter.daemons["pathd"] == 1: + elif need_mpls_for_ldp or nrouter.daemons["pathd"] == 1: # Enable MPLS processing on all interfaces. for interface in self.links: topotest.sysctl_assure( diff --git a/zebra/interface.c b/zebra/interface.c index b9150fcf6c82..75b8c0f8bd91 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -5395,6 +5395,23 @@ void mpls_interface_update(struct interface *ifp, uint8_t mpls) dplane_intf_mpls_modify_state(ifp, mpls); } +void zebra_interface_mpls_set(ZAPI_HANDLER_ARGS) +{ + struct interface *ifp; + bool mpls = false; + struct stream *s; + + s = msg; + ifp = zebra_interface_mpls_set_read(s, zvrf->vrf->vrf_id, &mpls); + if (!ifp) + return; + + if (mpls) + mpls_interface_update(ifp, IF_ZEBRA_DATA_ON); + else + mpls_interface_update(ifp, IF_ZEBRA_DATA_OFF); +} + static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, const char *label) diff --git a/zebra/interface.h b/zebra/interface.h index 5bfd0814d72c..ae8101886c03 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -17,6 +17,7 @@ #include "zebra/zebra_nhg_private.h" #include "zebra/zebra_router.h" #include "zebra/rtadv.h" +#include "zebra/zserv.h" #ifdef __cplusplus extern "C" { @@ -338,6 +339,7 @@ extern void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif); extern const char *zebra_protodown_rc_str(uint32_t protodown_rc, char *pd_buf, uint32_t pd_buf_len); extern void mpls_interface_update(struct interface *ifp, uint8_t mpls); +extern void zebra_interface_mpls_set(ZAPI_HANDLER_ARGS); void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx); extern void if_mpls_set_default(struct zebra_if *zif); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 2383f6aa8cdf..0c2d42aec750 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3887,6 +3887,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable, + [ZEBRA_INTERFACE_MPLS_SET] = zebra_interface_mpls_set, [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set, [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete, [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,