iface = if_lookup_name(ldeconf, kif->ifname);
if (iface) {
if_update_info(iface, kif);
+
+ /* if up see if any labels need to be updated */
+ if (kif->operative)
+ lde_route_update(iface, AF_UNSPEC);
break;
}
kr.remote_label = fnh->remote_label;
kr.route_type = fnh->route_type;
kr.route_instance = fnh->route_instance;
-
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
sizeof(kr));
break;
if (strcmp(af_conf->acl_label_expnull_for, filter_name) == 0)
lde_change_expnull_for_filter(af);
}
+
+void lde_route_update(struct iface *iface, int af)
+{
+ struct fec *f;
+ struct fec_node *fn;
+ struct fec_nh *fnh;
+ struct lde_nbr *ln;
+
+ /* update label of non-connected routes */
+ log_debug("update labels for interface %s", iface->name);
+ RB_FOREACH(f, fec_tree, &ft) {
+ fn = (struct fec_node *)f;
+ if (IS_MPLS_UNRESERVED_LABEL(fn->local_label))
+ continue;
+
+ switch (af) {
+ case AF_INET:
+ if (fn->fec.type != FEC_TYPE_IPV4)
+ continue;
+ break;
+ case AF_INET6:
+ if (fn->fec.type != FEC_TYPE_IPV6)
+ continue;
+ break;
+ default:
+ /* unspecified so process both address families */
+ break;
+ }
+
+ LIST_FOREACH(fnh, &fn->nexthops, entry) {
+ /*
+ * If connected leave existing label. If LDP
+ * configured on interface or a static route
+ * may need new label. If no LDP configured
+ * treat fec as a connected route
+ */
+ if (fnh->flags & F_FEC_NH_CONNECTED)
+ break;
+
+ if (fnh->ifindex != iface->ifindex)
+ continue;
+
+ fnh->flags &= ~F_FEC_NH_NO_LDP;
+ if (IS_MPLS_RESERVED_LABEL(fn->local_label)) {
+ fn->local_label = NO_LABEL;
+ fn->local_label = lde_update_label(fn);
+ if (fn->local_label != NO_LABEL)
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelmapping(
+ ln, fn, 0);
+ }
+ break;
+ }
+ }
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid,
+ 0, NULL, 0);
+}
+
+void lde_route_update_release(struct iface *iface, int af)
+{
+ struct lde_nbr *ln;
+ struct fec *f;
+ struct fec_node *fn;
+ struct fec_nh *fnh;
+
+ /* update label of interfaces no longer running LDP */
+ log_debug("release all labels for interface %s af %s", iface->name,
+ af == AF_INET ? "ipv4" : "ipv6");
+ RB_FOREACH(f, fec_tree, &ft) {
+ fn = (struct fec_node *)f;
+
+ switch (af) {
+ case AF_INET:
+ if (fn->fec.type != FEC_TYPE_IPV4)
+ continue;
+ break;
+ case AF_INET6:
+ if (fn->fec.type != FEC_TYPE_IPV6)
+ continue;
+ break;
+ default:
+ fatalx("lde_route_update_release: unknown af");
+ }
+
+ if (fn->local_label == NO_LABEL)
+ continue;
+
+ LIST_FOREACH(fnh, &fn->nexthops, entry) {
+ /*
+ * If connected leave existing label. If LDP
+ * removed from interface may need new label
+ * and would be treated as a connected route
+ */
+ if (fnh->flags & F_FEC_NH_CONNECTED)
+ break;
+
+ if (fnh->ifindex != iface->ifindex)
+ continue;
+
+ fnh->flags |= F_FEC_NH_NO_LDP;
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelwithdraw(ln, fn, NULL, NULL);
+ lde_free_label(fn->local_label);
+ fn->local_label = NO_LABEL;
+ fn->local_label = lde_update_label(fn);
+ if (fn->local_label != NO_LABEL)
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelmapping(ln, fn, 0);
+ break;
+ }
+ }
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid,
+ 0, NULL, 0);
+}
+
+void lde_route_update_release_all(int af)
+{
+ struct lde_nbr *ln;
+ struct fec *f;
+ struct fec_node *fn;
+ struct fec_nh *fnh;
+
+ /* remove labels from all interfaces as LDP is no longer running for
+ * this address family
+ */
+ log_debug("release all labels for address family %s",
+ af == AF_INET ? "ipv4" : "ipv6");
+ RB_FOREACH(f, fec_tree, &ft) {
+ fn = (struct fec_node *)f;
+ switch (af) {
+ case AF_INET:
+ if (fn->fec.type != FEC_TYPE_IPV4)
+ continue;
+ break;
+ case AF_INET6:
+ if (fn->fec.type != FEC_TYPE_IPV6)
+ continue;
+ break;
+ default:
+ fatalx("lde_route_update_release: unknown af");
+ }
+
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelwithdraw(ln, fn, NULL, NULL);
+
+ LIST_FOREACH(fnh, &fn->nexthops, entry) {
+ fnh->flags |= F_FEC_NH_NO_LDP;
+ lde_send_delete_klabel(fn, fnh);
+ }
+ }
+}
void lde_change_advertise_filter(int);
void lde_change_accept_filter(int);
void lde_change_expnull_for_filter(int);
+void lde_route_update(struct iface *, int);
+void lde_route_update_release(struct iface *, int);
+void lde_route_update_release_all(int);
struct lde_addr *lde_address_find(struct lde_nbr *, int,
union ldpd_addr *);
* if LDP configured on interface or a static route
* clear flag else treat fec as a connected route
*/
- iface = if_lookup(ldeconf,fnh->ifindex);
- if (iface || fnh->route_type == ZEBRA_ROUTE_STATIC)
- fnh->flags &=~F_FEC_NH_NO_LDP;
- else
+ if (ldeconf->flags & F_LDPD_ENABLED) {
+ iface = if_lookup(ldeconf,fnh->ifindex);
+ if (fnh->flags & F_FEC_NH_CONNECTED ||
+ iface ||
+ fnh->route_type == ZEBRA_ROUTE_STATIC)
+ fnh->flags &=~F_FEC_NH_NO_LDP;
+ else
+ fnh->flags |= F_FEC_NH_NO_LDP;
+ } else
fnh->flags |= F_FEC_NH_NO_LDP;
} else {
lde_send_delete_klabel(fn, fnh);
lde_send_labelmapping(ln, fn, 1);
}
+ /* if no label created yet then don't try to program labeled route */
+ if (fn->local_label == NO_LABEL)
+ return;
+
LIST_FOREACH(fnh, &fn->nexthops, entry) {
lde_send_change_klabel(fn, fnh);
fnh->flags &= ~F_FEC_NH_DEFER;
}
fnh->remote_label = map->label;
- lde_send_change_klabel(fn, fnh);
+ if (fn->local_label != NO_LABEL)
+ lde_send_change_klabel(fn, fnh);
break;
case FEC_TYPE_PWID:
pw = (struct l2vpn_pw *) fn->data;
"Show detailed information\n"
JSON_STR)
{
+ if (!(ldpd_conf->flags & F_LDPD_ENABLED))
+ return CMD_SUCCESS;
if (!local_label_str)
local_label = NO_LABEL;
if (!remote_label_str)
int reset_nbrs_ipv4 = 0;
int reset_nbrs = 0;
int update_sockets = 0;
+ int change_ldp_disabled = 0;
/* update timers */
if (af_conf->keepalive != xa->keepalive) {
!= (xa->flags & F_LDPD_AF_ALLOCHOSTONLY))
change_host_label = 1;
+ /* disabling LDP for address family */
+ if ((af_conf->flags & F_LDPD_AF_ENABLED) &&
+ !(xa->flags & F_LDPD_AF_ENABLED))
+ change_ldp_disabled = 1;
+
af_conf->flags = xa->flags;
/* update the transport address */
lde_change_egress_label(af);
if (change_host_label)
lde_change_allocate_filter(af);
+ if (change_ldp_disabled)
+ lde_route_update_release_all(af);
+
break;
case PROC_LDP_ENGINE:
if (stop_init_backoff)
struct iface *iface, *itmp, *xi;
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
- /* find deleted interfaces */
+ /* find deleted interfaces, which occurs when LDP is removed
+ * for all address families
+ */
if (if_lookup_name(xconf, iface->name) == NULL) {
switch (ldpd_process) {
case PROC_LDP_ENGINE:
ldpe_if_exit(iface);
break;
case PROC_LDE_ENGINE:
+ if (iface->ipv4.enabled)
+ lde_route_update_release(iface,
+ AF_INET);
+ if (iface->ipv6.enabled)
+ lde_route_update_release(iface,
+ AF_INET6);
+ break;
case PROC_MAIN:
break;
}
continue;
}
+ /* update labels when adding or removing ldp on an
+ * interface
+ */
+ if (ldpd_process == PROC_LDE_ENGINE) {
+ /* if we are removing lpd config for an address
+ * family on an interface then advertise routes
+ * learned over this interface as if they were
+ * connected routes
+ */
+ if (iface->ipv4.enabled && !xi->ipv4.enabled)
+ lde_route_update_release(iface, AF_INET);
+ if (iface->ipv6.enabled && !xi->ipv6.enabled)
+ lde_route_update_release(iface, AF_INET6);
+
+ /* if we are adding lpd config for an address
+ * family on an interface then add proper labels
+ */
+ if (!iface->ipv4.enabled && xi->ipv4.enabled)
+ lde_route_update(iface, AF_INET);
+ if (!iface->ipv6.enabled && xi->ipv6.enabled)
+ lde_route_update(iface, AF_INET6);
+ }
+
/* update existing interfaces */
merge_iface_af(&iface->ipv4, &xi->ipv4);
merge_iface_af(&iface->ipv6, &xi->ipv6);
map = imsg.data;
nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL) {
- log_debug("ldpe_dispatch_lde: cannot find neighbor");
+ if (nbr == NULL)
break;
- }
if (nbr->state != NBR_STA_OPER)
break;
case IMSG_REQUEST_ADD_END:
case IMSG_WITHDRAW_ADD_END:
nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL) {
- log_debug("ldpe_dispatch_lde: cannot find neighbor");
+ if (nbr == NULL)
break;
- }
if (nbr->state != NBR_STA_OPER)
break;
/* Maximum # labels that can be pushed. */
#define MPLS_MAX_LABELS 16
-#define IS_MPLS_RESERVED_LABEL(label) \
- (label >= MPLS_LABEL_RESERVED_MIN && label <= MPLS_LABEL_RESERVED_MAX)
+#define IS_MPLS_RESERVED_LABEL(label) (label <= MPLS_LABEL_RESERVED_MAX)
#define IS_MPLS_UNRESERVED_LABEL(label) \
(label >= MPLS_LABEL_UNRESERVED_MIN \