]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospfd: add support for suppress_fa
authorckishimo <carles.kishimoto@gmail.com>
Mon, 2 Nov 2020 14:28:52 +0000 (06:28 -0800)
committerCarles Kishimoto Bisbe <carles.kishimoto@cern.ch>
Wed, 24 Mar 2021 15:06:38 +0000 (16:06 +0100)
This command will trigger the OSPF forwarding address suppression in
translated type-5 LSAs, causing a NSSA ABR to use 0.0.0.0 as a forwarding
address instead of copying the address from the type-7 LSA

Example: In a topology like: R1 --- R2(ABR) --- R3(ASBR)

R3 is announcing a type-7 LSA that is translated to type-5 by the R2 ABR.
The forwarding address in the type-5 is by default copied from the type-7

    r1# sh ip os da external

                    AS External Link States

      LS age: 6
      Options: 0x2  : *|-|-|-|-|-|E|-
      LS Flags: 0x6
      LS Type: AS-external-LSA
      Link State ID: 3.3.3.3 (External Network Number)
      Advertising Router: 10.0.25.2
      LS Seq Number: 80000001
      Checksum: 0xcf99
      Length: 36

      Network Mask: /32
            Metric Type: 2 (Larger than any link state path)
            TOS: 0
            Metric: 20
            Forward Address: 10.0.23.3    <--- address copied from type-7 lsa
            External Route Tag: 0

    r2# sh ip os database

                    NSSA-external Link States (Area 0.0.0.1 [NSSA])

    Link ID         ADV Router      Age  Seq#       CkSum  Route
    3.3.3.3         10.0.23.3          8 0x80000001 0x431d E2 3.3.3.3/32 [0x0]

                    AS External Link States

    Link ID         ADV Router      Age  Seq#       CkSum  Route
    3.3.3.3         10.0.25.2          0 0x80000001 0xcf99 E2 3.3.3.3/32 [0x0]

    r2# conf t
    r2(config)# router ospf
    r2(config-router)# area 1 nssa suppress-fa
    r2(config-router)# exit
    r2(config)# exit

    r2# sh ip os database

                    NSSA-external Link States (Area 0.0.0.1 [NSSA])

    Link ID         ADV Router      Age  Seq#       CkSum  Route
    3.3.3.3         10.0.23.3         66 0x80000001 0x431d E2 3.3.3.3/32 [0x0]

                    AS External Link States

    Link ID         ADV Router      Age  Seq#       CkSum  Route
    3.3.3.3         10.0.25.2         16 0x80000002 0x0983 E2 3.3.3.3/32 [0x0]

    r1# sh ip os da external

           OSPF Router with ID (11.11.11.11)

                    AS External Link States

      LS age: 34
      Options: 0x2  : *|-|-|-|-|-|E|-
      LS Flags: 0x6
      LS Type: AS-external-LSA
      Link State ID: 3.3.3.3 (External Network Number)
      Advertising Router: 10.0.25.2
      LS Seq Number: 80000002
      Checksum: 0x0983
      Length: 36

      Network Mask: /32
            Metric Type: 2 (Larger than any link state path)
            TOS: 0
            Metric: 20
            Forward Address: 0.0.0.0       <--- address set to 0
            External Route Tag: 0

    r2# conf t
    r2(config)# router ospf
    r2(config-router)# no area 1 nssa suppress-fa
    r2(config-router)# exit

    r1# sh ip os da external

           OSPF Router with ID (11.11.11.11)

                    AS External Link States

      LS age: 1
      Options: 0x2  : *|-|-|-|-|-|E|-
      LS Flags: 0x6
      LS Type: AS-external-LSA
      Link State ID: 3.3.3.3 (External Network Number)
      Advertising Router: 10.0.25.2
      LS Seq Number: 80000003
      Checksum: 0xcb9b
      Length: 36
      Network Mask: /32
            Metric Type: 2 (Larger than any link state path)
            TOS: 0
            Metric: 20
            Forward Address: 0.0.0.0       <--- address set to 0
            External Route Tag: 0

    r2# conf t
    r2(config)# router ospf
    r2(config-router)# no area 1 nssa suppress-fa
    r2(config-router)# exit

    r1# sh ip os da external

           OSPF Router with ID (11.11.11.11)

                    AS External Link States

      LS age: 1
      Options: 0x2  : *|-|-|-|-|-|E|-
      LS Flags: 0x6
      LS Type: AS-external-LSA
      Link State ID: 3.3.3.3 (External Network Number)
      Advertising Router: 10.0.25.2
      LS Seq Number: 80000003
      Checksum: 0xcb9b
      Length: 36

      Network Mask: /32
            Metric Type: 2 (Larger than any link state path)
            TOS: 0
            Metric: 20
            Forward Address: 10.0.23.3    <--- address copied from type-7 lsa
            External Route Tag: 0

Signed-off-by: ckishimo <carles.kishimoto@gmail.com>
ospfd/ospf_abr.c
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index f3c4798906ca0b912c9d5051cc4579c5324797d3..b5c97eda3c908516156ea0f2073c04a4e64f1eca 100644 (file)
@@ -675,7 +675,8 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
                 * originate translated LSA
                 */
 
-               if (ospf_translated_nssa_originate(area->ospf, lsa) == NULL) {
+               if (ospf_translated_nssa_originate(area->ospf, lsa, old)
+                   == NULL) {
                        if (IS_DEBUG_OSPF_NSSA)
                                zlog_debug(
                                        "ospf_abr_translate_nssa(): Could not translate Type-7 for %pI4 to Type-5",
index 6bde5467b2785a9ebe035cc47db66ff1323f27a5..cb1c565d3770f73469ad626e03936985375b3969 100644 (file)
@@ -1765,7 +1765,14 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
        /* copy over Type-7 data to new */
        extnew->e[0].tos = ext->e[0].tos;
        extnew->e[0].route_tag = ext->e[0].route_tag;
-       extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
+       if (type7->area->suppress_fa) {
+               extnew->e[0].fwd_addr.s_addr = 0;
+               if (IS_DEBUG_OSPF_NSSA)
+                       zlog_debug(
+                               "ospf_lsa_translated_nssa_new(): Suppress forwarding address for %pI4",
+                               &ei.p.prefix);
+       } else
+               extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
        new->data->ls_seqnum = type7->data->ls_seqnum;
 
        /* add translated flag, checksum and lock new lsa */
@@ -1777,7 +1784,8 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
 
 /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
 struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
-                                               struct ospf_lsa *type7)
+                                               struct ospf_lsa *type7,
+                                               struct ospf_lsa *type5)
 {
        struct ospf_lsa *new;
        struct as_external_lsa *extnew;
@@ -1796,6 +1804,10 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
 
        extnew = (struct as_external_lsa *)new->data;
 
+       /* Update LSA sequence number from translated Type-5 LSA */
+       if (type5)
+               new->data->ls_seqnum = lsa_seqnum_increment(type5);
+
        if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) {
                flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
                          "%s: Could not install LSA id %pI4", __func__,
@@ -1823,6 +1835,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
                                              struct ospf_lsa *type5)
 {
        struct ospf_lsa *new = NULL;
+       struct as_external_lsa *extold = NULL;
+       uint32_t ls_seqnum = 0;
 
        /* Sanity checks. */
        assert(type7 || type5);
@@ -1887,6 +1901,12 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
                return NULL;
        }
 
+       extold = (struct as_external_lsa *)type5->data;
+       if (type7->area->suppress_fa == 1) {
+               if (extold->e[0].fwd_addr.s_addr == 0)
+                       ls_seqnum = ntohl(type5->data->ls_seqnum);
+       }
+
        /* Delete LSA from neighbor retransmit-list. */
        ospf_ls_retransmit_delete_nbr_as(ospf, type5);
 
@@ -1899,6 +1919,11 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
                return NULL;
        }
 
+       if (type7->area->suppress_fa == 1) {
+               if (extold->e[0].fwd_addr.s_addr == 0)
+                       new->data->ls_seqnum = htonl(ls_seqnum + 1);
+       }
+
        if (!(new = ospf_lsa_install(ospf, NULL, new))) {
                flog_warn(
                        EC_OSPF_LSA_INSTALL_FAILURE,
index f2a0d36e7e04810fdd36cc8fac692cf089d0e62e..3c1f94e6282b6ba5684bb9dd878d4325dc79b353 100644 (file)
@@ -341,11 +341,12 @@ extern char link_info_set(struct stream **s, struct in_addr id,
 
 extern struct in_addr ospf_get_nssa_ip(struct ospf_area *);
 extern int ospf_translated_nssa_compare(struct ospf_lsa *, struct ospf_lsa *);
-extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *,
-                                                    struct ospf_lsa *,
-                                                    struct ospf_lsa *);
-extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *,
-                                                      struct ospf_lsa *);
+extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
+                                                    struct ospf_lsa *type7,
+                                                    struct ospf_lsa *type5);
+extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
+                                                      struct ospf_lsa *type7,
+                                                      struct ospf_lsa *type5);
 extern void ospf_flush_lsa_from_area(struct ospf *ospf, struct in_addr area_id,
                                     int type);
 #endif /* _ZEBRA_OSPF_LSA_H */
index e6835ffc72060bec936a9629847585d1e521251e..d634853b3efcfbc6998357a7f6f167c3a583bb09 100644 (file)
@@ -1574,6 +1574,58 @@ DEFUN (ospf_area_nssa,
        return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0);
 }
 
+DEFUN(ospf_area_nssa_suppress_fa, ospf_area_nssa_suppress_fa_cmd,
+      "area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
+      "OSPF area parameters\n"
+      "OSPF area ID in IP address format\n"
+      "OSPF area ID as a decimal value\n"
+      "Configure OSPF area as nssa\n"
+      "Suppress forwarding address\n")
+{
+       int idx_ipv4_number = 1;
+       struct in_addr area_id;
+       int format;
+
+       VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+       VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
+                                  argv[idx_ipv4_number]->arg);
+
+       ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
+                                    format);
+       ospf_area_nssa_suppress_fa_set(ospf, area_id);
+
+       ospf_schedule_abr_task(ospf);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_ospf_area_nssa_suppress_fa, no_ospf_area_nssa_suppress_fa_cmd,
+      "no area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
+      NO_STR
+      "OSPF area parameters\n"
+      "OSPF area ID in IP address format\n"
+      "OSPF area ID as a decimal value\n"
+      "Configure OSPF area as nssa\n"
+      "Suppress forwarding address\n")
+{
+       int idx_ipv4_number = 2;
+       struct in_addr area_id;
+       int format;
+
+       VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+
+       VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format,
+                                  argv[idx_ipv4_number]->arg);
+
+       ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
+                                    format);
+       ospf_area_nssa_suppress_fa_unset(ospf, area_id);
+
+       ospf_schedule_abr_task(ospf);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (ospf_area_nssa_no_summary,
        ospf_area_nssa_no_summary_cmd,
        "area <A.B.C.D|(0-4294967295)> nssa no-summary",
@@ -11823,6 +11875,10 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf)
                                        vty_out(vty,
                                                " area %s nssa no-summary\n",
                                                buf);
+                               if (area->suppress_fa)
+                                       vty_out(vty,
+                                               " area %s nssa suppress-fa\n",
+                                               buf);
                        }
 
                        if (area->default_cost != 1)
@@ -12684,6 +12740,8 @@ void ospf_vty_init(void)
        install_element(OSPF_NODE, &ospf_area_nssa_translate_cmd);
        install_element(OSPF_NODE, &ospf_area_nssa_no_summary_cmd);
        install_element(OSPF_NODE, &no_ospf_area_nssa_no_summary_cmd);
+       install_element(OSPF_NODE, &ospf_area_nssa_suppress_fa_cmd);
+       install_element(OSPF_NODE, &no_ospf_area_nssa_suppress_fa_cmd);
        install_element(OSPF_NODE, &no_ospf_area_nssa_cmd);
 
        install_element(OSPF_NODE, &ospf_area_default_cost_cmd);
index 9856e601305fc42d562c85feb55c77d780af5886..f126577aeb96d9a5cc870d847fa18a1baba8ffb7 100644 (file)
@@ -1672,6 +1672,7 @@ int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
 
                /* set NSSA area defaults */
                area->no_summary = 0;
+               area->suppress_fa = 0;
                area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
                area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
                area->NSSATranslatorStabilityInterval =
@@ -1693,6 +1694,7 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
                ospf->anyNSSA--;
                /* set NSSA area defaults */
                area->no_summary = 0;
+               area->suppress_fa = 0;
                area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
                area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
                area->NSSATranslatorStabilityInterval =
@@ -1708,6 +1710,32 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
        return 1;
 }
 
+int ospf_area_nssa_suppress_fa_set(struct ospf *ospf, struct in_addr area_id)
+{
+       struct ospf_area *area;
+
+       area = ospf_area_lookup_by_area_id(ospf, area_id);
+       if (area == NULL)
+               return 0;
+
+       area->suppress_fa = 1;
+
+       return 1;
+}
+
+int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf, struct in_addr area_id)
+{
+       struct ospf_area *area;
+
+       area = ospf_area_lookup_by_area_id(ospf, area_id);
+       if (area == NULL)
+               return 0;
+
+       area->suppress_fa = 0;
+
+       return 1;
+}
+
 int ospf_area_nssa_translator_role_set(struct ospf *ospf,
                                       struct in_addr area_id, int role)
 {
index 5d64ee9ba21fa1da21a102297f6e9fe840a4f5c1..a3f78b074e855111adfed93f9f3f6a22cc8cb8ba 100644 (file)
@@ -476,7 +476,7 @@ struct ospf_area {
        int shortcut_capability; /* Other ABRs agree on S-bit */
        uint32_t default_cost;   /* StubDefaultCost. */
        int auth_type;           /* Authentication type. */
-
+       int suppress_fa;         /* Suppress forwarding address in NSSA ABR */
 
        uint8_t NSSATranslatorRole; /* NSSA configured role */
 #define OSPF_NSSA_ROLE_NEVER     0
@@ -668,6 +668,10 @@ extern int ospf_area_no_summary_set(struct ospf *, struct in_addr);
 extern int ospf_area_no_summary_unset(struct ospf *, struct in_addr);
 extern int ospf_area_nssa_set(struct ospf *, struct in_addr);
 extern int ospf_area_nssa_unset(struct ospf *, struct in_addr, int);
+extern int ospf_area_nssa_suppress_fa_set(struct ospf *ospf,
+                                         struct in_addr area_id);
+extern int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf,
+                                           struct in_addr area_id);
 extern int ospf_area_nssa_translator_role_set(struct ospf *, struct in_addr,
                                              int);
 extern int ospf_area_export_list_set(struct ospf *, struct ospf_area *,