]> git.proxmox.com Git - mirror_frr.git/blobdiff - ldpd/l2vpn.c
staticd: Do not ready prefix for printing till it's decoded
[mirror_frr.git] / ldpd / l2vpn.c
index f15461d3d2b0176d0f4f1bc6ff603a71b82d85bd..7f2e396a7f5c849f9e41bf51133eac3bbcd076a0 100644 (file)
@@ -76,16 +76,21 @@ l2vpn_del(struct l2vpn *l2vpn)
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
 
-       while ((lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree)) != NULL) {
+       while (!RB_EMPTY(l2vpn_if_head, &l2vpn->if_tree)) {
+               lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree);
+
                RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
                free(lif);
        }
-       while ((pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree)) != NULL) {
+       while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_tree)) {
+               pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree);
+
                RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
                free(pw);
        }
-       while ((pw = RB_ROOT(l2vpn_pw_head,
-           &l2vpn->pw_inactive_tree)) != NULL) {
+       while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_inactive_tree)) {
+               pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
+
                RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
                free(pw);
        }
@@ -114,7 +119,7 @@ l2vpn_exit(struct l2vpn *l2vpn)
 static __inline int
 l2vpn_if_compare(const struct l2vpn_if *a, const struct l2vpn_if *b)
 {
-       return (strcmp(a->ifname, b->ifname));
+       return if_cmp_name_func(a->ifname, b->ifname);
 }
 
 struct l2vpn_if *
@@ -177,7 +182,7 @@ l2vpn_if_update(struct l2vpn_if *lif)
 static __inline int
 l2vpn_pw_compare(const struct l2vpn_pw *a, const struct l2vpn_pw *b)
 {
-       return (strcmp(a->ifname, b->ifname));
+       return if_cmp_name_func(a->ifname, b->ifname);
 }
 
 struct l2vpn_pw *
@@ -235,9 +240,13 @@ void
 l2vpn_pw_init(struct l2vpn_pw *pw)
 {
        struct fec       fec;
+       struct zapi_pw   zpw;
 
        l2vpn_pw_reset(pw);
 
+       pw2zpw(pw, &zpw);
+       lde_imsg_compose_parent(IMSG_KPW_ADD, 0, &zpw, sizeof(zpw));
+
        l2vpn_pw_fec(pw, &fec);
        lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
            0, (void *)pw);
@@ -248,10 +257,14 @@ void
 l2vpn_pw_exit(struct l2vpn_pw *pw)
 {
        struct fec       fec;
+       struct zapi_pw   zpw;
 
        l2vpn_pw_fec(pw, &fec);
        lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0);
        lde_kernel_update(&fec);
+
+       pw2zpw(pw, &zpw);
+       lde_imsg_compose_parent(IMSG_KPW_DELETE, 0, &zpw, sizeof(zpw));
 }
 
 static void
@@ -269,7 +282,8 @@ l2vpn_pw_reset(struct l2vpn_pw *pw)
 {
        pw->remote_group = 0;
        pw->remote_mtu = 0;
-       pw->remote_status = 0;
+       pw->local_status = PW_FORWARDING;
+       pw->remote_status = PW_NOT_FORWARDING;
 
        if (pw->flags & F_PW_CWORD_CONF)
                pw->flags |= F_PW_CWORD;
@@ -286,17 +300,26 @@ int
 l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
 {
        /* check for a remote label */
-       if (fnh->remote_label == NO_LABEL)
+       if (fnh->remote_label == NO_LABEL) {
+               log_warnx("%s: pseudowire %s: no remote label", __func__,
+                         pw->ifname);
                return (0);
+       }
 
        /* MTUs must match */
-       if (pw->l2vpn->mtu != pw->remote_mtu)
+       if (pw->l2vpn->mtu != pw->remote_mtu) {
+               log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__,
+                         pw->ifname);
                return (0);
+       }
 
        /* check pw status if applicable */
        if ((pw->flags & F_PW_STATUSTLV) &&
-           pw->remote_status != PW_FORWARDING)
+           pw->remote_status != PW_FORWARDING) {
+               log_warnx("%s: pseudowire %s: remote end is down", __func__,
+                         pw->ifname);
                return (0);
+       }
 
        return (1);
 }
@@ -475,6 +498,56 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
        }
 }
 
+int
+l2vpn_pw_status_update(struct zapi_pw_status *zpw)
+{
+       struct l2vpn            *l2vpn;
+       struct l2vpn_pw         *pw = NULL;
+       struct lde_nbr          *ln;
+       struct fec               fec;
+       uint32_t                 local_status;
+
+       RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
+               pw = l2vpn_pw_find(l2vpn, zpw->ifname);
+               if (pw)
+                       break;
+       }
+       if (!pw) {
+               log_warnx("%s: pseudowire %s not found", __func__, zpw->ifname);
+               return (1);
+       }
+
+       if (zpw->status == PW_STATUS_UP)
+               local_status = PW_FORWARDING;
+       else
+               local_status = PW_NOT_FORWARDING;
+
+       /* local status didn't change */
+       if (pw->local_status == local_status)
+               return (0);
+       pw->local_status = local_status;
+
+       /* notify remote peer about the status update */
+       ln = lde_nbr_find_by_lsrid(pw->lsr_id);
+       if (ln == NULL)
+               return (0);
+       l2vpn_pw_fec(pw, &fec);
+       if (pw->flags & F_PW_STATUSTLV)
+               l2vpn_send_pw_status(ln, local_status, &fec);
+       else {
+               struct fec_node *fn;
+               fn = (struct fec_node *)fec_find(&ft, &fec);
+               if (fn) {
+                       if (pw->local_status == PW_FORWARDING)
+                               lde_send_labelmapping(ln, fn, 1);
+                       else
+                               lde_send_labelwithdraw(ln, fn, NULL, NULL);
+               }
+       }
+
+       return (0);
+}
+
 void
 l2vpn_pw_ctl(pid_t pid)
 {
@@ -491,7 +564,10 @@ l2vpn_pw_ctl(pid_t pid)
                            sizeof(pwctl.ifname));
                        pwctl.pwid = pw->pwid;
                        pwctl.lsr_id = pw->lsr_id;
-                       pwctl.status = pw->flags & F_PW_STATUS_UP;
+                       if (pw->enabled &&
+                           pw->local_status == PW_FORWARDING &&
+                           pw->remote_status == PW_FORWARDING)
+                               pwctl.status = 1;
 
                        lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
                            pid, &pwctl, sizeof(pwctl));