switch (imsg.hdr.type) {
case IMSG_NETWORK_ADD:
+ case IMSG_NETWORK_ADD_END:
case IMSG_NETWORK_DEL:
if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
log_warnx("%s: wrong imsg len", __func__);
lde_kernel_insert(&fec, kr.af, &kr.nexthop,
kr.priority, kr.flags & F_CONNECTED, NULL);
break;
+ case IMSG_NETWORK_ADD_END:
+ lde_kernel_reevaluate(&fec);
+ break;
case IMSG_NETWORK_DEL:
lde_kernel_remove(&fec, kr.af, &kr.nexthop,
kr.priority);
union ldpd_addr nexthop;
uint32_t remote_label;
uint8_t priority;
+ uint8_t flags;
};
+#define F_FEC_NH_NEW 0x01
struct fec_node {
struct fec fec;
uint8_t, int, void *);
void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
uint8_t);
+void lde_kernel_reevaluate(struct fec *);
void lde_check_mapping(struct map *, struct lde_nbr *);
void lde_check_request(struct map *, struct lde_nbr *);
void lde_check_release(struct map *, struct lde_nbr *);
fn = (struct fec_node *)fec_find(&ft, fec);
if (fn == NULL)
fn = fec_add(fec);
- if (fec_nh_find(fn, af, nexthop, priority) != NULL)
+ fnh = fec_nh_find(fn, af, nexthop, priority);
+ if (fnh != NULL) {
+ fnh->flags |= F_FEC_NH_NEW;
return;
+ }
if (fn->fec.type == FEC_TYPE_PWID)
fn->data = data;
}
fnh = fec_nh_add(fn, af, nexthop, priority);
+ fnh->flags |= F_FEC_NH_NEW;
lde_send_change_klabel(fn, fnh);
switch (fn->fec.type) {
}
}
+/*
+ * Whenever a route is changed, zebra advertises its new version without
+ * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
+ * message, we need to check for nexthops that were removed and, for each of
+ * them (if any), withdraw the associated labels from zebra.
+ */
+void
+lde_kernel_reevaluate(struct fec *fec)
+{
+ struct fec_node *fn;
+ struct fec_nh *fnh, *safe;
+
+ fn = (struct fec_node *)fec_find(&ft, fec);
+ if (fn == NULL)
+ return;
+
+ LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
+ if (fnh->flags & F_FEC_NH_NEW)
+ fnh->flags &= ~F_FEC_NH_NEW;
+ else
+ lde_kernel_remove(fec, fnh->af, &fnh->nexthop,
+ fnh->priority);
+ }
+}
+
void
lde_check_mapping(struct map *map, struct lde_nbr *ln)
{