]> git.proxmox.com Git - mirror_frr.git/commitdiff
OSPFd: Fix Opaque LSA filtering in Segment Routing
authorOlivier Dugeon <olivier.dugeon@orange.com>
Mon, 5 Feb 2018 19:24:17 +0000 (20:24 +0100)
committerOlivier Dugeon <olivier.dugeon@orange.com>
Mon, 5 Feb 2018 19:24:17 +0000 (20:24 +0100)
Opaque LSA were incorrectly filtered. LSA Type 1 with a
router id set to 4.x.x.x or 7.x.x.x. or 8.x.x.x are not correctly
filtered and pass to Segment Routing as wrong Opaque LSA of type
Router Information, Extended Prefix respectively Extended Link.
 - Add Opaque LSA check to the filter

The CLI command 'segment-routing prefix' didn't check if a same prefix
already exist in SRDB resulting to multiple entries in the SRDB for the
same prefix.
 - Update prefix intead of adding a new one if already present in the SRDB

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
ospfd/ospf_ext.c
ospfd/ospf_ri.c
ospfd/ospf_sr.c

index 819a695e0059159cf46de315be1076dca70b5f2d..d42476b6d859e8413c1a2eb12c63b041688fbc1f 100644 (file)
@@ -780,6 +780,11 @@ static int ospf_ext_link_lsa_update(struct ospf_lsa *lsa)
                return -1;
        }
 
+       /* Process only Opaque LSA */
+       if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
+           && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
+               return 0;
+
        /* Process only Extended Link LSA */
        if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
            != OPAQUE_TYPE_EXTENDED_LINK_LSA)
@@ -808,8 +813,9 @@ static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa)
                return -1;
        }
 
-       /* Check if it is not my LSA */
-       if (IS_LSA_SELF(lsa))
+       /* Process only Opaque LSA */
+       if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
+           && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
                return 0;
 
        /* Process only Extended Prefix LSA */
@@ -817,6 +823,10 @@ static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa)
            != OPAQUE_TYPE_EXTENDED_PREFIX_LSA)
                return 0;
 
+       /* Check if it is not my LSA */
+       if (IS_LSA_SELF(lsa))
+               return 0;
+
        /* Check if Extended is enable */
        if (!OspfEXT.enabled)
                return 0;
index a1d20fdd624d3973aa557861eb93b07dec82cc09..7c7a6fd795cf79f555d2bf16c0d9af53672920b8 100644 (file)
@@ -1051,8 +1051,9 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
                return -1;
        }
 
-       /* Check if it is not my LSA */
-       if (IS_LSA_SELF(lsa))
+       /* Process only Opaque LSA */
+       if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
+           && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
                return 0;
 
        /* Process only Router Information LSA */
@@ -1060,6 +1061,10 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
                        OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
                return 0;
 
+       /* Check if it is not my LSA */
+       if (IS_LSA_SELF(lsa))
+               return 0;
+
        /* Check if Router Info & Segment Routing are enable */
        if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
                return 0;
index 5586f24f6e062a23ca9c9d955309b2201600262e..725bf952e55a610daca4a921641d8858015614cd 100644 (file)
@@ -1148,7 +1148,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
        srgb.range_size = 0;
        srgb.lower_bound = 0;
 
-       for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+       for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
             tlvh = TLV_HDR_NEXT(tlvh)) {
                switch (ntohs(tlvh->type)) {
                case RI_SR_TLV_SR_ALGORITHM:
@@ -1296,7 +1296,7 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
        /* Initialize TLV browsing */
        length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
        sum = 0;
-       for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+       for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
             tlvh = TLV_HDR_NEXT(tlvh)) {
                if (ntohs(tlvh->type) == EXT_TLV_LINK) {
                        /* Got Extended Link information */
@@ -1950,17 +1950,15 @@ DEFUN (sr_prefix_sid,
        struct prefix p;
        uint32_t index;
        struct listnode *node;
-       struct sr_prefix *srp;
+       struct sr_prefix *srp, *new;
        struct interface *ifp;
-       int rc;
 
        if (!ospf_sr_enabled(vty))
                return CMD_WARNING_CONFIG_FAILED;
 
        /* Get network prefix */
        argv_find(argv, argc, "A.B.C.D/M", &idx);
-       rc = str2prefix(argv[idx]->arg, &p);
-       if (!rc) {
+       if (!str2prefix(argv[idx]->arg, &p)) {
                vty_out(vty, "Invalid prefix format %s\n",
                        argv[idx]->arg);
                return CMD_WARNING_CONFIG_FAILED;
@@ -1983,23 +1981,25 @@ DEFUN (sr_prefix_sid,
                }
        }
 
-       /* Add new Extended Prefix to SRDB */
-       srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
-       IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix, &p.u.prefix4);
-       IPV4_ADDR_COPY(&srp->nhlfe.nexthop, &p.u.prefix4);
-       srp->nhlfe.prefv4.prefixlen = p.prefixlen;
-       srp->nhlfe.prefv4.family = p.family;
-       srp->sid = index;
-       /* Set NO PHP flag if present */
-       if (argv_find(argv, argc, "no-php-flag", &idx))
-               SET_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
-       listnode_add(OspfSR.self->ext_prefix, srp);
+       /* Create new Extended Prefix to SRDB if not found */
+       new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
+       IPV4_ADDR_COPY(&new->nhlfe.prefv4.prefix, &p.u.prefix4);
+       IPV4_ADDR_COPY(&new->nhlfe.nexthop, &p.u.prefix4);
+       new->nhlfe.prefv4.prefixlen = p.prefixlen;
+       new->nhlfe.prefv4.family = p.family;
+       new->sid = index;
+       /* Set NO PHP flag if present and compute NHLFE */
+       if (argv_find(argv, argc, "no-php-flag", &idx)) {
+               SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
+               new->nhlfe.label_in = index2label(new->sid, OspfSR.self->srgb);
+               new->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
+       }
 
        if (IS_DEBUG_OSPF_SR)
                zlog_debug(
-                       "SR (%s): Add new Prefix %s/%u with index %u",
-                       __func__, inet_ntoa(srp->nhlfe.prefv4.prefix),
-                       srp->nhlfe.prefv4.prefixlen, index);
+                       "SR (%s): Add new index %u to Prefix %s/%u",
+                       __func__, index, inet_ntoa(new->nhlfe.prefv4.prefix),
+                       new->nhlfe.prefv4.prefixlen);
 
        /* Get Interface and check if it is a Loopback */
        ifp = if_lookup_prefix(&p, VRF_DEFAULT);
@@ -2010,6 +2010,7 @@ DEFUN (sr_prefix_sid,
                 * ready. In this case, store the prefix SID for latter
                 * update of this Extended Prefix
                 */
+               listnode_add(OspfSR.self->ext_prefix, new);
                zlog_warn(
                        "Interface for prefix %s/%u not found. Deferred LSA "
                        "flooding", inet_ntoa(p.u.prefix4), p.prefixlen);
@@ -2018,23 +2019,34 @@ DEFUN (sr_prefix_sid,
 
        if (!if_is_loopback(ifp)) {
                vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
-               listnode_delete(OspfSR.self->ext_prefix, srp);
-               XFREE(MTYPE_OSPF_SR_PARAMS, srp);
+               XFREE(MTYPE_OSPF_SR_PARAMS, new);
                return CMD_WARNING_CONFIG_FAILED;
        }
-       srp->nhlfe.ifindex = ifp->ifindex;
+       new->nhlfe.ifindex = ifp->ifindex;
 
-       /* Install NHLFE if NO-PHP is requested */
-       if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)) {
-               srp->nhlfe.label_in = index2label(srp->sid, OspfSR.self->srgb);
-               srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
-               add_sid_nhlfe(srp->nhlfe);
+       /* Search if this prefix already exist */
+       for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
+               if ((IPV4_ADDR_SAME(&srp->nhlfe.prefv4.prefix, &p.u.prefix4)
+                   && srp->nhlfe.prefv4.prefixlen == p.prefixlen))
+                       break;
+               else
+                       srp = NULL;
+       }
+
+       /* Update or Add this new SR Prefix */
+       if (srp) {
+               update_sid_nhlfe(srp->nhlfe, new->nhlfe);
+               listnode_delete(OspfSR.self->ext_prefix, srp);
+               listnode_add(OspfSR.self->ext_prefix, new);
+       } else {
+               listnode_add(OspfSR.self->ext_prefix, new);
+               add_sid_nhlfe(new->nhlfe);
        }
 
        /* Finally, update Extended Prefix LSA */
-       srp->instance = ospf_ext_schedule_prefix_index(ifp, srp->sid,
-                               &srp->nhlfe.prefv4, srp->flags);
-       if (srp->instance) {
+       new->instance = ospf_ext_schedule_prefix_index(ifp, new->sid,
+                               &new->nhlfe.prefv4, new->flags);
+       if (new->instance == 0) {
                vty_out(vty, "Unable to set index %u for prefix %s/%u\n", index,
                        inet_ntoa(p.u.prefix4), p.prefixlen);
                return CMD_WARNING;