]> git.proxmox.com Git - mirror_frr.git/blobdiff - bfdd/ptm_adapter.c
Merge pull request #5450 from donaldsharp/rpki_node_issues
[mirror_frr.git] / bfdd / ptm_adapter.c
index 93d8a442e344bae78e774f5a5c7c75e4c5f43a26..dcca70b796f07751debf14f17b1eb2dfd998404f 100644 (file)
@@ -58,7 +58,7 @@ static struct zclient *zclient;
 static int _ptm_msg_address(struct stream *msg, int family, const void *addr);
 
 static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa);
-static int _ptm_msg_read(struct stream *msg, int command,
+static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
                         struct bfd_peer_cfg *bpc, struct ptm_client **pc);
 
 static struct ptm_client *pc_lookup(uint32_t pid);
@@ -72,8 +72,8 @@ static struct ptm_client_notification *pcn_lookup(struct ptm_client *pc,
 static void pcn_free(struct ptm_client_notification *pcn);
 
 
-static void bfdd_dest_register(struct stream *msg);
-static void bfdd_dest_deregister(struct stream *msg);
+static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id);
+static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id);
 static void bfdd_client_register(struct stream *msg);
 static void bfdd_client_deregister(struct stream *msg);
 
@@ -89,6 +89,7 @@ static void debug_printbpc(const char *func, unsigned int line,
 {
        char addr[3][128];
        char timers[3][128];
+       char cbit_str[10];
 
        addr[0][0] = addr[1][0] = addr[2][0] = timers[0][0] = timers[1][0] =
                timers[2][0] = 0;
@@ -117,9 +118,11 @@ static void debug_printbpc(const char *func, unsigned int line,
                snprintf(timers[2], sizeof(timers[2]), " detect-multiplier:%d",
                         bpc->bpc_detectmultiplier);
 
-       log_debug("%s:%d: %s %s%s%s%s%s%s", func, line,
+       sprintf(cbit_str, "CB %x", bpc->bpc_cbit);
+
+       log_debug("%s:%d: %s %s%s%s%s%s%s %s", func, line,
                  bpc->bpc_mhop ? "multi-hop" : "single-hop", addr[0], addr[1],
-                 addr[2], timers[0], timers[1], timers[2]);
+                 addr[2], timers[0], timers[1], timers[2], cbit_str);
 }
 
 #define DEBUG_PRINTBPC(bpc) debug_printbpc(__FILE__, __LINE__, (bpc))
@@ -150,7 +153,7 @@ static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
        return 0;
 }
 
-int ptm_bfd_notify(struct bfd_session *bs)
+int ptm_bfd_notify(struct bfd_session *bs, uint8_t notify_state)
 {
        struct stream *msg;
 
@@ -173,6 +176,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
         *   - AF_INET6:
         *     - 16 bytes: ipv6
         *   - c: prefix length
+        * - c: cbit
         *
         * Commands: ZEBRA_BFD_DEST_REPLAY
         *
@@ -182,7 +186,10 @@ int ptm_bfd_notify(struct bfd_session *bs)
        stream_reset(msg);
 
        /* TODO: VRF handling */
-       zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT);
+       if (bs->vrf)
+               zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, bs->vrf->vrf_id);
+       else
+               zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT);
 
        /* This header will be handled by `zebra_ptm.c`. */
        stream_putl(msg, ZEBRA_INTERFACE_BFD_DEST_UPDATE);
@@ -197,12 +204,15 @@ int ptm_bfd_notify(struct bfd_session *bs)
        _ptm_msg_address(msg, bs->key.family, &bs->key.peer);
 
        /* BFD status */
-       switch (bs->ses_state) {
+       switch (notify_state) {
        case PTM_BFD_UP:
                stream_putl(msg, BFD_STATUS_UP);
                break;
 
        case PTM_BFD_ADM_DOWN:
+               stream_putl(msg, BFD_STATUS_ADMIN_DOWN);
+               break;
+
        case PTM_BFD_DOWN:
        case PTM_BFD_INIT:
                stream_putl(msg, BFD_STATUS_DOWN);
@@ -216,6 +226,8 @@ int ptm_bfd_notify(struct bfd_session *bs)
        /* BFD source prefix information. */
        _ptm_msg_address(msg, bs->key.family, &bs->key.local);
 
+       stream_putc(msg, bs->remote_cbit);
+
        /* Write packet size. */
        stream_putw_at(msg, 0, stream_get_endp(msg));
 
@@ -256,7 +268,7 @@ stream_failure:
        memset(sa, 0, sizeof(*sa));
 }
 
-static int _ptm_msg_read(struct stream *msg, int command,
+static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
                         struct bfd_peer_cfg *bpc, struct ptm_client **pc)
 {
        uint32_t pid;
@@ -290,6 +302,7 @@ static int _ptm_msg_read(struct stream *msg, int command,
         *       - 16 bytes: ipv6 address
         *     - c: ifname length
         *     - X bytes: interface name
+        * - c: bfd_cbit
         *
         * q(64), l(32), w(16), c(8)
         */
@@ -355,6 +368,23 @@ static int _ptm_msg_read(struct stream *msg, int command,
                        bpc->bpc_localif[ifnamelen] = 0;
                }
        }
+       if (vrf_id != VRF_DEFAULT) {
+               struct vrf *vrf;
+
+               vrf = vrf_lookup_by_id(vrf_id);
+               if (vrf) {
+                       bpc->bpc_has_vrfname = true;
+                       strlcpy(bpc->bpc_vrfname, vrf->name, sizeof(bpc->bpc_vrfname));
+               } else {
+                       log_error("ptm-read: vrf id %u could not be identified", vrf_id);
+                       return -1;
+               }
+       } else {
+               bpc->bpc_has_vrfname = true;
+               strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
+       }
+
+       STREAM_GETC(msg, bpc->bpc_cbit);
 
        /* Sanity check: peer and local address must match IP types. */
        if (bpc->bpc_local.sa_sin.sin_family != 0
@@ -370,7 +400,7 @@ stream_failure:
        return -1;
 }
 
-static void bfdd_dest_register(struct stream *msg)
+static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id)
 {
        struct ptm_client *pc;
        struct ptm_client_notification *pcn;
@@ -378,7 +408,7 @@ static void bfdd_dest_register(struct stream *msg)
        struct bfd_peer_cfg bpc;
 
        /* Read the client context and peer data. */
-       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, &bpc, &pc) == -1)
+       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, vrf_id, &bpc, &pc) == -1)
                return;
 
        DEBUG_PRINTBPC(&bpc);
@@ -405,10 +435,10 @@ static void bfdd_dest_register(struct stream *msg)
                return;
        }
 
-       ptm_bfd_notify(bs);
+       ptm_bfd_notify(bs, bs->ses_state);
 }
 
-static void bfdd_dest_deregister(struct stream *msg)
+static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
 {
        struct ptm_client *pc;
        struct ptm_client_notification *pcn;
@@ -416,7 +446,7 @@ static void bfdd_dest_deregister(struct stream *msg)
        struct bfd_peer_cfg bpc;
 
        /* Read the client context and peer data. */
-       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, &bpc, &pc) == -1)
+       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, vrf_id, &bpc, &pc) == -1)
                return;
 
        DEBUG_PRINTBPC(&bpc);
@@ -434,6 +464,10 @@ static void bfdd_dest_deregister(struct stream *msg)
        if (bs->refcount ||
            BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
                return;
+
+       bs->ses_state = PTM_BFD_ADM_DOWN;
+       ptm_bfd_snd(bs, 0);
+
        ptm_bfd_sess_del(&bpc);
 }
 
@@ -497,10 +531,10 @@ static int bfdd_replay(ZAPI_CALLBACK_ARGS)
        switch (rcmd) {
        case ZEBRA_BFD_DEST_REGISTER:
        case ZEBRA_BFD_DEST_UPDATE:
-               bfdd_dest_register(msg);
+               bfdd_dest_register(msg, vrf_id);
                break;
        case ZEBRA_BFD_DEST_DEREGISTER:
-               bfdd_dest_deregister(msg);
+               bfdd_dest_deregister(msg, vrf_id);
                break;
        case ZEBRA_BFD_CLIENT_REGISTER:
                bfdd_client_register(msg);
@@ -548,15 +582,19 @@ static void bfdd_sessions_enable_interface(struct interface *ifp)
 {
        struct bfd_session_observer *bso;
        struct bfd_session *bs;
+       struct vrf *vrf;
 
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
-               if (bso->bso_isinterface == false)
-                       continue;
-
-               /* Interface name mismatch. */
                bs = bso->bso_bs;
+               /* Interface name mismatch. */
                if (strcmp(ifp->name, bs->key.ifname))
                        continue;
+               vrf = vrf_lookup_by_id(ifp->vrf_id);
+               if (!vrf)
+                       continue;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
                /* Skip enabled sessions. */
                if (bs->sock != -1)
                        continue;
@@ -572,10 +610,6 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
        struct bfd_session *bs;
 
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
-               if (bso->bso_isinterface == false)
-                       continue;
-
-               /* Interface name mismatch. */
                bs = bso->bso_bs;
                if (strcmp(ifp->name, bs->key.ifname))
                        continue;
@@ -583,39 +617,62 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
                if (bs->sock == -1)
                        continue;
 
-               /* Try to enable it. */
                bfd_session_disable(bs);
 
-               TAILQ_INSERT_HEAD(&bglobal.bg_obslist, bso, bso_entry);
        }
 }
 
-static int bfdd_interface_update(ZAPI_CALLBACK_ARGS)
+void bfdd_sessions_enable_vrf(struct vrf *vrf)
 {
-       struct interface *ifp;
-
-       /*
-        * `zebra_interface_add_read` will handle the interface creation
-        * on `lib/if.c`. We'll use that data structure instead of
-        * rolling our own.
-        */
-       if (cmd == ZEBRA_INTERFACE_ADD) {
-               ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
-               if (ifp == NULL)
-                       return 0;
+       struct bfd_session_observer *bso;
+       struct bfd_session *bs;
 
-               bfdd_sessions_enable_interface(ifp);
-               return 0;
+       /* it may affect configs without interfaces */
+       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               bs = bso->bso_bs;
+               /* update name */
+               if (bs->vrf && bs->vrf == vrf) {
+                       if (!strmatch(bs->key.vrfname, vrf->name))
+                               bfd_session_update_vrf_name(bs, vrf);
+               }
+               if (bs->vrf)
+                       continue;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
+               /* need to update the vrf information on
+                * bs so that callbacks are handled
+                */
+               bs->vrf = vrf;
+               /* Skip enabled sessions. */
+               if (bs->sock != -1)
+                       continue;
+               /* Try to enable it. */
+               bfd_session_enable(bs);
        }
+}
 
-       /* Update interface information. */
-       ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
-       if (ifp == NULL)
-               return 0;
+void bfdd_sessions_disable_vrf(struct vrf *vrf)
+{
+       struct bfd_session_observer *bso;
+       struct bfd_session *bs;
 
-       bfdd_sessions_disable_interface(ifp);
+       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               bs = bso->bso_bs;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
+               /* Skip disabled sessions. */
+               if (bs->sock == -1)
+                       continue;
+
+               bfd_session_disable(bs);
+       }
+}
 
-       if_set_index(ifp, IFINDEX_INTERNAL);
+static int bfd_ifp_destroy(struct interface *ifp)
+{
+       bfdd_sessions_disable_interface(ifp);
 
        return 0;
 }
@@ -641,9 +698,6 @@ static void bfdd_sessions_enable_address(struct connected *ifc)
        struct prefix prefix;
 
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
-               if (bso->bso_isaddress == false)
-                       continue;
-
                /* Skip enabled sessions. */
                bs = bso->bso_bs;
                if (bs->sock != -1)
@@ -673,8 +727,16 @@ static int bfdd_interface_address_update(ZAPI_CALLBACK_ARGS)
        return 0;
 }
 
+static int bfd_ifp_create(struct interface *ifp)
+{
+       bfdd_sessions_enable_interface(ifp);
+
+       return 0;
+}
+
 void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
 {
+       if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy);
        zclient = zclient_new(master, &zclient_options_default);
        assert(zclient != NULL);
        zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);
@@ -689,10 +751,6 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
        /* Send replay request on zebra connect. */
        zclient->zebra_connected = bfdd_zebra_connected;
 
-       /* Learn interfaces from zebra instead of the OS. */
-       zclient->interface_add = bfdd_interface_update;
-       zclient->interface_delete = bfdd_interface_update;
-
        /* Learn about interface VRF. */
        zclient->interface_vrf_update = bfdd_interface_vrf_update;
 
@@ -701,6 +759,20 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
        zclient->interface_address_delete = bfdd_interface_address_update;
 }
 
+void bfdd_zclient_register(vrf_id_t vrf_id)
+{
+       if (!zclient || zclient->sock < 0)
+               return;
+       zclient_send_reg_requests(zclient, vrf_id);
+}
+
+void bfdd_zclient_unregister(vrf_id_t vrf_id)
+{
+       if (!zclient || zclient->sock < 0)
+               return;
+       zclient_send_dereg_requests(zclient, vrf_id);
+}
+
 void bfdd_zclient_stop(void)
 {
        zclient_stop(zclient);