]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf6d: extend the "redistribute" command with more options 9503/head
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 26 Aug 2021 16:10:41 +0000 (13:10 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Thu, 26 Aug 2021 18:05:53 +0000 (15:05 -0300)
Add the "metric" and "metric-type" options to the "redistribute"
command.

This is a small commit since the logic of setting the metric
value and type of external routes was already present due to the
implementation of the "default-information originate" command months
ago. This commit merely extends the "redistribute" command to
leverage that functionality.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
doc/user/ospf6d.rst
ospf6d/ospf6_asbr.c
tests/topotests/ospf6_topo2/test_ospf6_topo2.py

index dd4e7d6dc158db7760715ece4aba3b527c667ac7..499788ae87ed53939ef23295e9028a3ff62c4513 100644 (file)
@@ -248,9 +248,11 @@ Usage of *ospfd6*'s route-map support.
 Redistribute routes to OSPF6
 ============================
 
-.. clicmd:: redistribute <babel|bgp|connected|isis|kernel|openfabric|ripng|sharp|static|table> [route-map WORD]
+.. clicmd:: redistribute <babel|bgp|connected|isis|kernel|openfabric|ripng|sharp|static|table> [metric-type (1-2)] [metric (0-16777214)] [route-map WORD]
 
-   Redistribute routes from other protocols into OSPFv3.
+   Redistribute routes of the specified protocol or kind into OSPFv3, with the
+   metric type and metric set if specified, filtering the routes using the
+   given route-map if specified.
 
 .. clicmd:: default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]
 
index acecf90023129bba118000e7addabbc78dad67c5..f16a1975a8cbde85f9cecf4168a672f9164ba8b4 100644 (file)
@@ -1641,72 +1641,55 @@ void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
        ospf6_asbr_status_update(ospf6, ospf6->redistribute);
 }
 
-DEFUN (ospf6_redistribute,
+DEFPY (ospf6_redistribute,
        ospf6_redistribute_cmd,
-       "redistribute " FRR_REDIST_STR_OSPF6D,
-       "Redistribute\n"
-       FRR_REDIST_HELP_STR_OSPF6D)
-{
-       int type;
-       struct ospf6_redist *red;
-
-       VTY_DECLVAR_CONTEXT(ospf6, ospf6);
-
-       char *proto = argv[argc - 1]->text;
-
-       type = proto_redistnum(AFI_IP6, proto);
-       if (type < 0)
-               return CMD_WARNING_CONFIG_FAILED;
-
-       red = ospf6_redist_lookup(ospf6, type, 0);
-       if (!red) {
-               ospf6_redist_add(ospf6, type, 0);
-       } else {
-               /* To check, if user is providing same config */
-               if (ROUTEMAP_NAME(red) == NULL)
-                       return CMD_SUCCESS;
-
-               ospf6_asbr_redistribute_unset(ospf6, red, type);
-       }
-
-       ospf6_asbr_redistribute_set(ospf6, type);
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (ospf6_redistribute_routemap,
-       ospf6_redistribute_routemap_cmd,
-       "redistribute " FRR_REDIST_STR_OSPF6D " route-map WORD",
+       "redistribute " FRR_REDIST_STR_OSPF6D "[{metric (0-16777214)|metric-type (1-2)$metric_type|route-map WORD$rmap_str}]",
        "Redistribute\n"
        FRR_REDIST_HELP_STR_OSPF6D
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1/2 metrics\n"
        "Route map reference\n"
        "Route map name\n")
 {
-       int idx_protocol = 1;
-       int idx_word = 3;
        int type;
        struct ospf6_redist *red;
+       int idx_protocol = 1;
+       char *proto = argv[idx_protocol]->text;
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
 
-       char *proto = argv[idx_protocol]->text;
        type = proto_redistnum(AFI_IP6, proto);
        if (type < 0)
                return CMD_WARNING_CONFIG_FAILED;
 
+       if (!metric_str)
+               metric = -1;
+       if (!metric_type_str)
+               metric_type = -1;
+
        red = ospf6_redist_lookup(ospf6, type, 0);
        if (!red) {
                red = ospf6_redist_add(ospf6, type, 0);
        } else {
-               /* To check, if user is providing same route map */
-               if ((ROUTEMAP_NAME(red) != NULL)
-                   && (strcmp(argv[idx_word]->arg, ROUTEMAP_NAME(red)) == 0))
+               /* Check if nothing has changed. */
+               if (red->dmetric.value == metric
+                   && red->dmetric.type == metric_type
+                   && ((!ROUTEMAP_NAME(red) && !rmap_str)
+                       || (ROUTEMAP_NAME(red) && rmap_str
+                           && strmatch(ROUTEMAP_NAME(red), rmap_str))))
                        return CMD_SUCCESS;
 
                ospf6_asbr_redistribute_unset(ospf6, red, type);
        }
 
-       ospf6_asbr_routemap_set(red, argv[idx_word]->arg);
+       red->dmetric.value = metric;
+       red->dmetric.type = metric_type;
+       if (rmap_str)
+               ospf6_asbr_routemap_set(red, rmap_str);
+       else
+               ospf6_asbr_routemap_unset(red);
        ospf6_asbr_redistribute_set(ospf6, type);
 
        return CMD_SUCCESS;
@@ -1714,20 +1697,24 @@ DEFUN (ospf6_redistribute_routemap,
 
 DEFUN (no_ospf6_redistribute,
        no_ospf6_redistribute_cmd,
-       "no redistribute " FRR_REDIST_STR_OSPF6D " [route-map WORD]",
+       "no redistribute " FRR_REDIST_STR_OSPF6D "[{metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
        NO_STR
        "Redistribute\n"
        FRR_REDIST_HELP_STR_OSPF6D
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1/2 metrics\n"
        "Route map reference\n"
        "Route map name\n")
 {
-       int idx_protocol = 2;
        int type;
        struct ospf6_redist *red;
+       int idx_protocol = 2;
+       char *proto = argv[idx_protocol]->text;
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
 
-       char *proto = argv[idx_protocol]->text;
        type = proto_redistnum(AFI_IP6, proto);
        if (type < 0)
                return CMD_WARNING_CONFIG_FAILED;
@@ -1754,11 +1741,14 @@ int ospf6_redistribute_config_write(struct vty *vty, struct ospf6 *ospf6)
                if (type == ZEBRA_ROUTE_OSPF6)
                        continue;
 
+               vty_out(vty, " redistribute %s", ZROUTE_NAME(type));
+               if (red->dmetric.value >= 0)
+                       vty_out(vty, " metric %d", red->dmetric.value);
+               if (red->dmetric.type != DEFAULT_METRIC_TYPE)
+                       vty_out(vty, " metric-type 1");
                if (ROUTEMAP_NAME(red))
-                       vty_out(vty, " redistribute %s route-map %s\n",
-                               ZROUTE_NAME(type), ROUTEMAP_NAME(red));
-               else
-                       vty_out(vty, " redistribute %s\n", ZROUTE_NAME(type));
+                       vty_out(vty, " route-map %s", ROUTEMAP_NAME(red));
+               vty_out(vty, "\n");
        }
 
        return 0;
@@ -2566,7 +2556,6 @@ void ospf6_asbr_init(void)
        install_element(OSPF6_NODE,
                        &no_ospf6_default_information_originate_cmd);
        install_element(OSPF6_NODE, &ospf6_redistribute_cmd);
-       install_element(OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
        install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd);
 }
 
index b6c8cf3e750a024fc3eb044693423021ac955b4a..8c5f1e6f607615301745fb194994b674e0c50fc7 100644 (file)
@@ -73,15 +73,20 @@ def expect_lsas(router, area, lsas, wait=5, extra_params=""):
     assert result is None, assertmsg
 
 
-def expect_ospfv3_routes(router, routes, wait=5):
+def expect_ospfv3_routes(router, routes, wait=5, detail=False):
     "Run command `ipv6 ospf6 route` and expect route with type."
     tgen = get_topogen()
 
+    if detail == False:
+        cmd = "show ipv6 ospf6 route json"
+    else:
+        cmd = "show ipv6 ospf6 route detail json"
+
     logger.info("waiting OSPFv3 router '{}' route".format(router))
     test_func = partial(
         topotest.router_json_cmp,
         tgen.gears[router],
-        "show ipv6 ospf6 route json",
+        cmd,
         {"routes": routes}
     )
     _, result = topotest.run_and_expect(test_func, None, count=wait, wait=1)
@@ -236,6 +241,51 @@ def test_ospf6_default_route():
     expect_route("r1", "::/0", metric + 10)
 
 
+def test_redistribute_metrics():
+    """
+    Test that the configured metrics are honored when a static route is
+    redistributed.
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Add new static route on r3.
+    config = """
+    configure terminal
+    ipv6 route 2001:db8:500::/64 Null0
+    """
+    tgen.gears["r3"].vtysh_cmd(config)
+
+    route = {
+        "2001:db8:500::/64": {
+            "metricType":2, 
+            "metricCost":10,
+        }
+    }
+    logger.info("Expecting AS-external route 2001:db8:500::/64 to show up with default metrics")
+    expect_ospfv3_routes("r2", route, wait=30, detail=True)
+
+    # Change the metric of redistributed routes of the static type on r3.
+    config = """
+    configure terminal
+    router ospf6
+    redistribute static metric 50 metric-type 1
+    """
+    tgen.gears["r3"].vtysh_cmd(config)
+
+    # Check if r3 reinstalled 2001:db8:500::/64 using the new metric type and value.
+    route = {
+        "2001:db8:500::/64": {
+            "metricType":1, 
+            "metricCost":60,
+        }
+    }
+    logger.info("Expecting AS-external route 2001:db8:500::/64 to show up with updated metric type and value")
+    expect_ospfv3_routes("r2", route, wait=30, detail=True)
+
+
+
 def test_nssa_lsa_type7():
     """
     Test that static route gets announced as external route when redistributed