]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_te.c
Merge pull request #4272 from opensourcerouting/isis-prefix-sid-fix
[mirror_frr.git] / ospfd / ospf_te.c
index 16347f1c5bbfe730c98bf148f23d09bd869f5786..1488aa88cd4edadbc8f6ec8bcfa37f9807b179d1 100644 (file)
@@ -150,7 +150,7 @@ static int ospf_mpls_te_register(enum inter_as_mode mode)
        return rc;
 }
 
-static int ospf_mpls_te_unregister()
+static int ospf_mpls_te_unregister(void)
 {
        uint8_t scope;
 
@@ -397,53 +397,13 @@ static void set_linkparams_link_type(struct ospf_interface *oi,
        return;
 }
 
-static void set_linkparams_link_id(struct ospf_interface *oi,
-                                  struct mpls_te_link *lp)
+static void set_linkparams_link_id(struct mpls_te_link *lp,
+                                  struct in_addr link_id)
 {
-       struct ospf_neighbor *nbr;
-       int done = 0;
 
        lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID);
        lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
-
-       /*
-        * The Link ID is identical to the contents of the Link ID field
-        * in the Router LSA for these link types.
-        */
-       switch (oi->type) {
-       case OSPF_IFTYPE_POINTOPOINT:
-               /* Take the router ID of the neighbor. */
-               if ((nbr = ospf_nbr_lookup_ptop(oi))
-                   && nbr->state == NSM_Full) {
-                       lp->link_id.value = nbr->router_id;
-                       done = 1;
-               }
-               break;
-       case OSPF_IFTYPE_BROADCAST:
-       case OSPF_IFTYPE_NBMA:
-               /* Take the interface address of the designated router. */
-               if ((nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi))) == NULL)
-                       break;
-
-               if (nbr->state == NSM_Full
-                   || (IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi))
-                       && ospf_nbr_count(oi, NSM_Full) > 0)) {
-                       lp->link_id.value = DR(oi);
-                       done = 1;
-               }
-               break;
-       default:
-               /* Not supported yet. */ /* XXX */
-               lp->link_id.header.type = htons(0);
-               break;
-       }
-
-       if (!done) {
-               struct in_addr mask;
-               masklen2ip(oi->address->prefixlen, &mask);
-               lp->link_id.value.s_addr =
-                       oi->address->u.prefix4.s_addr & mask.s_addr;
-       }
+       lp->link_id.value = link_id;
        return;
 }
 
@@ -958,40 +918,33 @@ void ospf_mpls_te_update_if(struct interface *ifp)
        return;
 }
 
+/*
+ * Just add interface and set available information. Other information
+ * and flooding of LSA will be done later when adjacency will be up
+ * See ospf_mpls_te_nsm_change() after
+ */
 static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
 {
-       struct te_link_subtlv_link_type old_type;
-       struct te_link_subtlv_link_id old_id;
+
        struct mpls_te_link *lp;
 
-       if ((lp = lookup_linkparams_by_ifp(oi->ifp)) == NULL) {
+       lp = lookup_linkparams_by_ifp(oi->ifp);
+       if (lp == NULL) {
                flog_warn(
                        EC_OSPF_TE_UNEXPECTED,
-                       "ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?",
-                       IF_NAME(oi));
+                       "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
+                       __func__, IF_NAME(oi));
                return;
        }
 
        if (oi->area == NULL || oi->area->ospf == NULL) {
                flog_warn(
                        EC_OSPF_TE_UNEXPECTED,
-                       "ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
-                       IF_NAME(oi));
+                       "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
+                       __func__, IF_NAME(oi));
                return;
        }
-#ifdef notyet
-       if ((lp->area != NULL
-            && !IPV4_ADDR_SAME(&lp->area->area_id, &oi->area->area_id))
-           || (lp->area != NULL && oi->area == NULL)) {
-               /* How should we consider this case? */
-               flog_warn(
-                       EC_OSPF_TE_UNEXPECTED,
-                       "MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs",
-                       IF_NAME(oi),
-                       oi->area ? inet_ntoa(oi->area->area_id) : "N/A");
-               ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
-       }
-#endif
+
        /* Keep Area information in combination with linkparams. */
        lp->area = oi->area;
 
@@ -1003,55 +956,103 @@ static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
        case ISM_DROther:
        case ISM_Backup:
        case ISM_DR:
-               old_type = lp->link_type;
-               old_id = lp->link_id;
-
-               /* Set Link type, Link ID, Local and Remote IP addr */
+               /* Set Link type and Local IP addr */
                set_linkparams_link_type(oi, lp);
-               set_linkparams_link_id(oi, lp);
                set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
 
-               if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) {
-                       struct prefix *pref = CONNECTED_PREFIX(oi->connected);
-                       if (pref != NULL)
-                               set_linkparams_rmtif_ipaddr(lp,
-                                                           pref->u.prefix4);
-               }
-
-               /* Update TE parameters */
-               update_linkparams(lp);
-
-               /* Try to Schedule LSA */
-               if ((ntohs(old_type.header.type)
-                            != ntohs(lp->link_type.header.type)
-                    || old_type.link_type.value
-                               != lp->link_type.link_type.value)
-                   || (ntohs(old_id.header.type)
-                               != ntohs(lp->link_id.header.type)
-                       || ntohl(old_id.value.s_addr)
-                                  != ntohl(lp->link_id.value.s_addr))) {
-                       if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
-                               ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
-                       else
-                               ospf_mpls_te_lsa_schedule(lp,
-                                                         REORIGINATE_THIS_LSA);
-               }
                break;
        default:
-               lp->link_type.header.type = htons(0);
-               lp->link_id.header.type = htons(0);
-
+               /* State is undefined: Flush LSA if engaged */
                if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
                        ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
                break;
        }
 
+       if (IS_DEBUG_OSPF_TE)
+               zlog_debug(
+                       "MPLS-TE(%s): Update Link parameters for interface %s",
+                       __func__, IF_NAME(oi));
+
        return;
 }
 
+/*
+ * Complete TE info and schedule LSA flooding
+ * Link-ID and Remote IP address must be set with neighbor info
+ * which are only valid once NSM state is FULL
+ */
 static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
 {
-       /* Nothing to do here */
+       struct ospf_interface *oi = nbr->oi;
+       struct mpls_te_link *lp;
+
+       /* Process Neighbor only when its state is NSM Full */
+       if (nbr->state != NSM_Full)
+               return;
+
+       /* Get interface information for Traffic Engineering */
+       lp = lookup_linkparams_by_ifp(oi->ifp);
+       if (lp == NULL) {
+               flog_warn(
+                       EC_OSPF_TE_UNEXPECTED,
+                       "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
+                       __func__, IF_NAME(oi));
+               return;
+       }
+
+       if (oi->area == NULL || oi->area->ospf == NULL) {
+               flog_warn(
+                       EC_OSPF_TE_UNEXPECTED,
+                       "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
+                       __func__, IF_NAME(oi));
+               return;
+       }
+
+       /* Keep Area information in combination with SR info. */
+       lp->area = oi->area;
+
+       /* Keep interface MPLS-TE status */
+       lp->flags = HAS_LINK_PARAMS(oi->ifp);
+
+       /*
+        * The Link ID is identical to the contents of the Link ID field
+        * in the Router LSA for these link types.
+        */
+       switch (oi->state) {
+       case ISM_PointToPoint:
+               /* Set Link ID with neighbor Router ID */
+               set_linkparams_link_id(lp, nbr->router_id);
+               /* Set Remote IP address */
+               set_linkparams_rmtif_ipaddr(lp, nbr->address.u.prefix4);
+               break;
+
+       case ISM_DR:
+       case ISM_DROther:
+       case ISM_Backup:
+               /* Set Link ID with the Designated Router ID */
+               set_linkparams_link_id(lp, DR(oi));
+               break;
+
+       default:
+               /* State is undefined: Flush LSA if engaged */
+               if (OspfMplsTE.enabled &&
+                       CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
+                       ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
+               return;
+       }
+
+       if (IS_DEBUG_OSPF_TE)
+               zlog_debug(
+                       "MPLS-TE (%s): Add Link-ID %s for interface %s ",
+                       __func__, inet_ntoa(lp->link_id.value), oi->ifp->name);
+
+       /* Try to Schedule LSA */
+       if (OspfMplsTE.enabled) {
+               if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
+                       ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
+               else
+                       ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
+       }
        return;
 }
 
@@ -2530,8 +2531,8 @@ DEFUN (show_ip_ospf_mpls_te_link,
        "Interface name\n")
 {
        struct vrf *vrf;
-       int idx_interface = 5;
-       struct interface *ifp;
+       int idx_interface = 0;
+       struct interface *ifp = NULL;
        struct listnode *node;
        char *vrf_name = NULL;
        bool all_vrf;
@@ -2543,7 +2544,7 @@ DEFUN (show_ip_ospf_mpls_te_link,
                vrf_name = argv[idx_vrf + 1]->arg;
                all_vrf = strmatch(vrf_name, "all");
        }
-
+       argv_find(argv, argc, "INTERFACE", &idx_interface);
        /* vrf input is provided could be all or specific vrf*/
        if (vrf_name) {
                if (all_vrf) {
@@ -2557,32 +2558,31 @@ DEFUN (show_ip_ospf_mpls_te_link,
                        return CMD_SUCCESS;
                }
                ospf = ospf_lookup_by_inst_name(inst, vrf_name);
-               if (ospf == NULL || !ospf->oi_running)
-                       return CMD_SUCCESS;
-               vrf = vrf_lookup_by_id(ospf->vrf_id);
-               FOR_ALL_INTERFACES (vrf, ifp)
-                       show_mpls_te_link_sub(vty, ifp);
+       } else
+               ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+       if (ospf == NULL || !ospf->oi_running)
                return CMD_SUCCESS;
-       }
-       /* Show All Interfaces. */
-       if (argc == 5) {
-               for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
-                       if (!ospf->oi_running)
-                               continue;
-                       vrf = vrf_lookup_by_id(ospf->vrf_id);
-                       FOR_ALL_INTERFACES (vrf, ifp)
-                               show_mpls_te_link_sub(vty, ifp);
+
+       vrf = vrf_lookup_by_id(ospf->vrf_id);
+       if (!vrf)
+               return CMD_SUCCESS;
+       if (idx_interface) {
+               ifp = if_lookup_by_name(
+                                       argv[idx_interface]->arg,
+                                       ospf->vrf_id);
+               if (ifp == NULL) {
+                       vty_out(vty, "No such interface name in vrf %s\n",
+                               vrf->name);
+                       return CMD_SUCCESS;
                }
        }
-       /* Interface name is specified. */
-       else {
-               ifp = if_lookup_by_name_all_vrf(argv[idx_interface]->arg);
-               if (ifp == NULL)
-                       vty_out(vty, "No such interface name\n");
-               else
+       if (!ifp) {
+               FOR_ALL_INTERFACES (vrf, ifp)
                        show_mpls_te_link_sub(vty, ifp);
+               return CMD_SUCCESS;
        }
 
+       show_mpls_te_link_sub(vty, ifp);
        return CMD_SUCCESS;
 }