diff options
author | Olivier Dugeon <olivier.dugeon@orange.com> | 2019-04-26 18:59:34 +0200 |
---|---|---|
committer | Olivier Dugeon <olivier.dugeon@orange.com> | 2019-04-30 16:19:59 +0200 |
commit | 01c9b80ad276f4f42ded0a48c432c3cd1a14993b (patch) | |
tree | d864ad1aed747eb4c720ced4792b71f316b47a54 /ospfd/ospf_te.c | |
parent | Merge pull request #4201 from Orange-OpenSource/SR-isis (diff) | |
download | frr-01c9b80ad276f4f42ded0a48c432c3cd1a14993b.tar.xz frr-01c9b80ad276f4f42ded0a48c432c3cd1a14993b.zip |
ospfd: Correct Link-ID and Remote IP for TE LSA
Solve issue #4198
Link-ID and Remote IP address must be set accordingly to the interface type
(Point-to-Point or Broadcast) from the neighbor information. However, this
information are only valid once the Network State Machine (NSM) is Full i.e.
when the adjacency is up. The original TE code only look to Interface State
Machine (ISM) change which not allow to collect valid neighbor information.
The patch move setup of Link-ID and Remote-IP TE parameters from
ospf_mpls_te_ism_change() to ospf_mpls_te_nsm_change() function.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Diffstat (limited to 'ospfd/ospf_te.c')
-rw-r--r-- | ospfd/ospf_te.c | 195 |
1 files changed, 98 insertions, 97 deletions
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index bd8cbee11..1488aa88c 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -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; } |