]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib, ospfd, yang: add route map set for min/max metric
authorJafar Al-Gharaibeh <jafar@atcorp.com>
Thu, 6 Apr 2023 04:55:13 +0000 (23:55 -0500)
committerJafar Al-Gharaibeh <jafar@atcorp.com>
Tue, 18 Apr 2023 05:48:16 +0000 (00:48 -0500)
Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
lib/routemap.c
lib/routemap.h
lib/routemap_cli.c
lib/routemap_northbound.c
ospfd/ospf_asbr.c
ospfd/ospf_asbr.h
ospfd/ospf_routemap.c
yang/frr-route-map.yang

index 20dcd2a53d4dc73589f666ee4e8509e7c7a69ad2..39455841e33b1a33537172af842f4021f09496da 100644 (file)
@@ -394,6 +394,40 @@ void route_map_no_set_metric_hook(int (*func)(struct route_map_index *index,
 {
        rmap_match_set_hook.no_set_metric = func;
 }
+/* set min-metric */
+void route_map_set_min_metric_hook(int (*func)(struct route_map_index *index,
+                                              const char *command,
+                                              const char *arg, char *errmsg,
+                                              size_t errmsg_len))
+{
+       rmap_match_set_hook.set_min_metric = func;
+}
+
+/* no set min-metric */
+void route_map_no_set_min_metric_hook(int (*func)(struct route_map_index *index,
+                                                 const char *command,
+                                                 const char *arg, char *errmsg,
+                                                 size_t errmsg_len))
+{
+       rmap_match_set_hook.no_set_min_metric = func;
+}
+/* set max-metric */
+void route_map_set_max_metric_hook(int (*func)(struct route_map_index *index,
+                                              const char *command,
+                                              const char *arg, char *errmsg,
+                                              size_t errmsg_len))
+{
+       rmap_match_set_hook.set_max_metric = func;
+}
+
+/* no set max-metric */
+void route_map_no_set_max_metric_hook(int (*func)(struct route_map_index *index,
+                                                 const char *command,
+                                                 const char *arg, char *errmsg,
+                                                 size_t errmsg_len))
+{
+       rmap_match_set_hook.no_set_max_metric = func;
+}
 
 /* set tag */
 void route_map_set_tag_hook(int (*func)(struct route_map_index *index,
index 2197a49e76c9ebdcbd1949a86a9a0f20e814e307..770d7058372f8a473bfdedf26aa0babfc1a8d44b 100644 (file)
@@ -312,6 +312,8 @@ DECLARE_QOBJ_TYPE(route_map);
        (strmatch(A, "frr-route-map:ipv6-next-hop"))
 #define IS_SET_METRIC(A)                                                       \
        (strmatch(A, "frr-route-map:set-metric"))
+#define IS_SET_MIN_METRIC(A) (strmatch(A, "frr-route-map:set-min-metric"))
+#define IS_SET_MAX_METRIC(A) (strmatch(A, "frr-route-map:set-max-metric"))
 #define IS_SET_TAG(A) (strmatch(A, "frr-route-map:set-tag"))
 #define IS_SET_SR_TE_COLOR(A)                                                  \
        (strmatch(A, "frr-route-map:set-sr-te-color"))
@@ -684,6 +686,22 @@ extern void route_map_no_set_metric_hook(
        int (*func)(struct route_map_index *index,
                    const char *command, const char *arg,
                    char *errmsg, size_t errmsg_len));
+/* set metric */
+extern void route_map_set_max_metric_hook(
+       int (*func)(struct route_map_index *index, const char *command,
+                   const char *arg, char *errmsg, size_t errmsg_len));
+/* no set metric */
+extern void route_map_no_set_max_metric_hook(
+       int (*func)(struct route_map_index *index, const char *command,
+                   const char *arg, char *errmsg, size_t errmsg_len));
+/* set metric */
+extern void route_map_set_min_metric_hook(
+       int (*func)(struct route_map_index *index, const char *command,
+                   const char *arg, char *errmsg, size_t errmsg_len));
+/* no set metric */
+extern void route_map_no_set_min_metric_hook(
+       int (*func)(struct route_map_index *index, const char *command,
+                   const char *arg, char *errmsg, size_t errmsg_len));
 /* set tag */
 extern void route_map_set_tag_hook(int (*func)(struct route_map_index *index,
                                               const char *command,
@@ -920,6 +938,25 @@ struct route_map_match_set_hooks {
        int (*no_set_metric)(struct route_map_index *index,
                             const char *command, const char *arg,
                             char *errmsg, size_t errmsg_len);
+       /* set min-metric */
+       int (*set_min_metric)(struct route_map_index *index,
+                             const char *command, const char *arg,
+                             char *errmsg, size_t errmsg_len);
+
+       /* no set min-metric */
+       int (*no_set_min_metric)(struct route_map_index *index,
+                                const char *command, const char *arg,
+                                char *errmsg, size_t errmsg_len);
+
+       /* set max-metric */
+       int (*set_max_metric)(struct route_map_index *index,
+                             const char *command, const char *arg,
+                             char *errmsg, size_t errmsg_len);
+
+       /* no set max-metric */
+       int (*no_set_max_metric)(struct route_map_index *index,
+                                const char *command, const char *arg,
+                                char *errmsg, size_t errmsg_len);
 
        /* set tag */
        int (*set_tag)(struct route_map_index *index,
index 4345b74bc0c1227d8b777cbbabee71fde76dbe1a..75d1175886f1364356ef4afaf77716f13b80aed2 100644 (file)
@@ -890,6 +890,76 @@ DEFPY_YANG(
        return nb_cli_apply_changes(vty, NULL);
 }
 
+DEFPY_YANG(set_min_metric, set_min_metric_cmd,
+          "set min-metric <(0-4294967295)$metric>",
+          SET_STR
+          "Minimum metric value for destination routing protocol\n"
+          "Minimum metric value\n")
+{
+       const char *xpath =
+               "./set-action[action='frr-route-map:set-min-metric']";
+       char xpath_value[XPATH_MAXLEN];
+       char value[64];
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-set-action/min-metric", xpath);
+       snprintf(value, sizeof(value), "%s", metric_str);
+
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_set_min_metric, no_set_min_metric_cmd,
+          "no set min-metric [(0-4294967295)]",
+          NO_STR SET_STR
+          "Minimum metric value for destination routing protocol\n"
+          "Minumum metric value\n")
+{
+       const char *xpath =
+               "./set-action[action='frr-route-map:set-min-metric']";
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(set_max_metric, set_max_metric_cmd,
+          "set max-metric <(0-4294967295)$metric>",
+          SET_STR
+          "Maximum metric value for destination routing protocol\n"
+          "Miximum metric value\n")
+{
+       const char *xpath =
+               "./set-action[action='frr-route-map:set-max-metric']";
+       char xpath_value[XPATH_MAXLEN];
+       char value[64];
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-set-action/max-metric", xpath);
+       snprintf(value, sizeof(value), "%s", metric_str);
+
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_set_max_metric, no_set_max_metric_cmd,
+          "no set max-metric [(0-4294967295)]",
+          NO_STR SET_STR
+          "Maximum Metric value for destination routing protocol\n"
+          "Maximum metric value\n")
+{
+       const char *xpath =
+               "./set-action[action='frr-route-map:set-max-metric']";
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
 DEFPY_YANG(
        set_tag, set_tag_cmd,
        "set tag (1-4294967295)$tag",
@@ -1011,6 +1081,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
                                yang_dnode_get_string(
                                        dnode, "./rmap-set-action/value"));
                }
+       } else if (IS_SET_MIN_METRIC(action)) {
+               vty_out(vty, " set min-metric %s\n",
+                       yang_dnode_get_string(dnode,
+                                             "./rmap-set-action/min-metric"));
+       } else if (IS_SET_MAX_METRIC(action)) {
+               vty_out(vty, " set max-metric %s\n",
+                       yang_dnode_get_string(dnode,
+                                             "./rmap-set-action/max-metric"));
        } else if (IS_SET_TAG(action)) {
                vty_out(vty, " set tag %s\n",
                        yang_dnode_get_string(dnode, "./rmap-set-action/tag"));
@@ -1551,6 +1629,12 @@ void route_map_cli_init(void)
        install_element(RMAP_NODE, &set_metric_cmd);
        install_element(RMAP_NODE, &no_set_metric_cmd);
 
+       install_element(RMAP_NODE, &set_min_metric_cmd);
+       install_element(RMAP_NODE, &no_set_min_metric_cmd);
+
+       install_element(RMAP_NODE, &set_max_metric_cmd);
+       install_element(RMAP_NODE, &no_set_max_metric_cmd);
+
        install_element(RMAP_NODE, &set_tag_cmd);
        install_element(RMAP_NODE, &no_set_tag_cmd);
 
index ab127dd0fcbf4e718136d0aa0e9c7bd1868f56aa..465985099429c3e45eff7b9d5ed9db5abbc3a7d1 100644 (file)
@@ -1027,6 +1027,110 @@ lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args *args)
        return lib_route_map_entry_set_destroy(args);
 }
 
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/set-action/min-metric
+ */
+static int set_action_min_metric_modify(enum nb_event event,
+                                       const struct lyd_node *dnode,
+                                       union nb_resource *resource,
+                                       const char *value, char *errmsg,
+                                       size_t errmsg_len)
+{
+       struct routemap_hook_context *rhc;
+       int rv;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       /* Check for hook function. */
+       if (rmap_match_set_hook.set_min_metric == NULL)
+               return NB_OK;
+
+       /* Add configuration. */
+       rhc = nb_running_get_entry(dnode, NULL, true);
+
+       /* Set destroy information. */
+       rhc->rhc_shook = rmap_match_set_hook.no_set_min_metric;
+       rhc->rhc_rule = "min-metric";
+
+       rv = rmap_match_set_hook.set_min_metric(rhc->rhc_rmi, "min-metric",
+                                               value, errmsg, errmsg_len);
+       if (rv != CMD_SUCCESS) {
+               rhc->rhc_shook = NULL;
+               return NB_ERR_INCONSISTENCY;
+       }
+
+       return NB_OK;
+}
+
+static int
+lib_route_map_entry_set_action_min_metric_modify(struct nb_cb_modify_args *args)
+{
+       const char *min_metric = yang_dnode_get_string(args->dnode, NULL);
+
+       return set_action_min_metric_modify(args->event, args->dnode,
+                                           args->resource, min_metric,
+                                           args->errmsg, args->errmsg_len);
+}
+
+static int lib_route_map_entry_set_action_min_metric_destroy(
+       struct nb_cb_destroy_args *args)
+{
+       return lib_route_map_entry_set_destroy(args);
+}
+
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/set-action/max-metric
+ */
+static int set_action_max_metric_modify(enum nb_event event,
+                                       const struct lyd_node *dnode,
+                                       union nb_resource *resource,
+                                       const char *value, char *errmsg,
+                                       size_t errmsg_len)
+{
+       struct routemap_hook_context *rhc;
+       int rv;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       /* Check for hook function. */
+       if (rmap_match_set_hook.set_max_metric == NULL)
+               return NB_OK;
+
+       /* Add configuration. */
+       rhc = nb_running_get_entry(dnode, NULL, true);
+
+       /* Set destroy information. */
+       rhc->rhc_shook = rmap_match_set_hook.no_set_max_metric;
+       rhc->rhc_rule = "max-metric";
+
+       rv = rmap_match_set_hook.set_max_metric(rhc->rhc_rmi, "max-metric",
+                                               value, errmsg, errmsg_len);
+       if (rv != CMD_SUCCESS) {
+               rhc->rhc_shook = NULL;
+               return NB_ERR_INCONSISTENCY;
+       }
+
+       return NB_OK;
+}
+
+static int
+lib_route_map_entry_set_action_max_metric_modify(struct nb_cb_modify_args *args)
+{
+       const char *max_metric = yang_dnode_get_string(args->dnode, NULL);
+
+       return set_action_max_metric_modify(args->event, args->dnode,
+                                           args->resource, max_metric,
+                                           args->errmsg, args->errmsg_len);
+}
+
+static int lib_route_map_entry_set_action_max_metric_destroy(
+       struct nb_cb_destroy_args *args)
+{
+       return lib_route_map_entry_set_destroy(args);
+}
+
 /*
  * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
  */
@@ -1368,6 +1472,20 @@ const struct frr_yang_module_info frr_route_map_info = {
                                .destroy = lib_route_map_entry_set_action_value_destroy,
                        }
                },
+               {
+                       .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/min-metric",
+                       .cbs = {
+                               .modify = lib_route_map_entry_set_action_min_metric_modify,
+                               .destroy = lib_route_map_entry_set_action_min_metric_destroy,
+                       }
+               },
+               {
+                       .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/max-metric",
+                       .cbs = {
+                               .modify = lib_route_map_entry_set_action_max_metric_modify,
+                               .destroy = lib_route_map_entry_set_action_max_metric_destroy,
+                       }
+               },
                {
                        .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-metric",
                        .cbs = {
index 516ee80c5b300c8d4fc415c2c2f19caa74c3348c..1b68f6e02236e72eb83ee146fbb12ea93f917c87 100644 (file)
@@ -132,6 +132,8 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
        new->orig_tag = tag;
        new->aggr_route = NULL;
        new->metric = metric;
+       new->min_metric = 0;
+       new->max_metric = OSPF_LS_INFINITY;
 
        /* we don't unlock rn from the get() because we're attaching the info */
        if (rn)
index 256a6c8b5bdd66efc11289ae2c9e5c701970a37b..dfb9d965c54b1ad3a95cd9da3150501d7c9123d1 100644 (file)
@@ -37,6 +37,8 @@ struct external_info {
        route_tag_t orig_tag;
 
        uint32_t metric;
+       uint32_t min_metric;
+       uint32_t max_metric;
 
        struct route_map_set_values route_map_set;
 #define ROUTEMAP_METRIC(E) (E)->route_map_set.metric
index 965686774510c36d464107f4c48cb31d2089551d..d2f639031be6a07f375895d30e5c34f48c9ea0b6 100644 (file)
@@ -398,17 +398,19 @@ route_set_metric(void *rule, const struct prefix *prefix, void *object)
        if (!metric->used)
                return RMAP_OKAY;
 
-       ei->route_map_set.metric = ei->metric;
+       ROUTEMAP_METRIC(ei) = ei->metric;
 
        if (metric->type == metric_increment)
-               ei->route_map_set.metric += metric->metric;
+               ROUTEMAP_METRIC(ei) += metric->metric;
        else if (metric->type == metric_decrement)
-               ei->route_map_set.metric -= metric->metric;
+               ROUTEMAP_METRIC(ei) -= metric->metric;
        else if (metric->type == metric_absolute)
-               ei->route_map_set.metric = metric->metric;
+               ROUTEMAP_METRIC(ei) = metric->metric;
 
-       if (ei->route_map_set.metric > OSPF_LS_INFINITY)
-               ei->route_map_set.metric = OSPF_LS_INFINITY;
+       if ((uint32_t)ROUTEMAP_METRIC(ei) < ei->min_metric)
+               ROUTEMAP_METRIC(ei) = ei->min_metric;
+       if ((uint32_t)ROUTEMAP_METRIC(ei) > ei->max_metric)
+               ROUTEMAP_METRIC(ei) = ei->max_metric;
 
        return RMAP_OKAY;
 }
@@ -462,6 +464,115 @@ static const struct route_map_rule_cmd route_set_metric_cmd = {
        route_set_metric_free,
 };
 
+/* `set min-metric METRIC' */
+/* Set min-metric to attribute. */
+static enum route_map_cmd_result_t
+route_set_min_metric(void *rule, const struct prefix *prefix, void *object)
+{
+       uint32_t *min_metric;
+       struct external_info *ei;
+
+       /* Fetch routemap's rule information. */
+       min_metric = rule;
+       ei = object;
+
+       ei->min_metric = *min_metric;
+
+       if (ei->min_metric > OSPF_LS_INFINITY)
+               ei->min_metric = OSPF_LS_INFINITY;
+
+       if ((uint32_t)ROUTEMAP_METRIC(ei) < ei->min_metric)
+               ROUTEMAP_METRIC(ei) = ei->min_metric;
+
+       return RMAP_OKAY;
+}
+
+/* set min-metric compilation. */
+static void *route_set_min_metric_compile(const char *arg)
+{
+
+       uint32_t *min_metric;
+
+       min_metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
+
+       *min_metric = strtoul(arg, NULL, 10);
+
+       if (*min_metric)
+               return min_metric;
+
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, min_metric);
+       return NULL;
+}
+
+/* Free route map's compiled `set min-metric' value. */
+static void route_set_min_metric_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+static const struct route_map_rule_cmd route_set_min_metric_cmd = {
+       "min-metric",
+       route_set_min_metric,
+       route_set_min_metric_compile,
+       route_set_min_metric_free,
+};
+
+
+/* `set max-metric METRIC' */
+/* Set max-metric to attribute. */
+static enum route_map_cmd_result_t
+route_set_max_metric(void *rule, const struct prefix *prefix, void *object)
+{
+       uint32_t *max_metric;
+       struct external_info *ei;
+
+       /* Fetch routemap's rule information. */
+       max_metric = rule;
+       ei = object;
+
+       ei->max_metric = *max_metric;
+
+       if (ei->max_metric > OSPF_LS_INFINITY)
+               ei->max_metric = OSPF_LS_INFINITY;
+
+       if ((uint32_t)ROUTEMAP_METRIC(ei) > ei->max_metric)
+               ROUTEMAP_METRIC(ei) = ei->max_metric;
+
+       return RMAP_OKAY;
+}
+
+/* set max-metric compilation. */
+static void *route_set_max_metric_compile(const char *arg)
+{
+
+       uint32_t *max_metric;
+
+       max_metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
+
+       *max_metric = strtoul(arg, NULL, 10);
+
+       if (*max_metric)
+               return max_metric;
+
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, max_metric);
+       return NULL;
+}
+
+/* Free route map's compiled `set max-metric' value. */
+static void route_set_max_metric_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+static const struct route_map_rule_cmd route_set_max_metric_cmd = {
+       "max-metric",
+       route_set_max_metric,
+       route_set_max_metric_compile,
+       route_set_max_metric_free,
+};
+
 /* `set metric-type TYPE' */
 /* Set metric-type to attribute. */
 static enum route_map_cmd_result_t
@@ -475,7 +586,7 @@ route_set_metric_type(void *rule, const struct prefix *prefix, void *object)
        ei = object;
 
        /* Set metric out value. */
-       ei->route_map_set.metric_type = *metric_type;
+       ROUTEMAP_METRIC_TYPE(ei) = *metric_type;
 
        return RMAP_OKAY;
 }
@@ -582,9 +693,6 @@ void ospf_route_map_init(void)
        route_map_delete_hook(ospf_route_map_update);
        route_map_event_hook(ospf_route_map_event);
 
-       route_map_set_metric_hook(generic_set_add);
-       route_map_no_set_metric_hook(generic_set_delete);
-
        route_map_match_ip_next_hop_hook(generic_match_add);
        route_map_no_match_ip_next_hop_hook(generic_match_delete);
 
@@ -609,6 +717,12 @@ void ospf_route_map_init(void)
        route_map_set_metric_hook(generic_set_add);
        route_map_no_set_metric_hook(generic_set_delete);
 
+       route_map_set_min_metric_hook(generic_set_add);
+       route_map_no_set_min_metric_hook(generic_set_delete);
+
+       route_map_set_max_metric_hook(generic_set_add);
+       route_map_no_set_max_metric_hook(generic_set_delete);
+
        route_map_set_tag_hook(generic_set_add);
        route_map_no_set_tag_hook(generic_set_delete);
 
@@ -621,6 +735,8 @@ void ospf_route_map_init(void)
        route_map_install_match(&route_match_tag_cmd);
 
        route_map_install_set(&route_set_metric_cmd);
+       route_map_install_set(&route_set_min_metric_cmd);
+       route_map_install_set(&route_set_max_metric_cmd);
        route_map_install_set(&route_set_metric_type_cmd);
        route_map_install_set(&route_set_tag_cmd);
 
index 224b2caef777d77097bc49fe62b8217c519527e6..7cb13b60f2fc2b271e4946ea7a61979b02774f95 100644 (file)
@@ -160,6 +160,18 @@ module frr-route-map {
       "Set prefix/route metric";
   }
 
+  identity set-min-metric {
+    base rmap-set-type;
+    description
+      "Set minimum prefix/route metric";
+  }
+
+    identity set-max-metric {
+    base rmap-set-type;
+    description
+      "Set maximum prefix/route metric";
+  }
+
   identity set-tag {
     base rmap-set-type;
     description
@@ -346,6 +358,39 @@ module frr-route-map {
           }
         }
 
+        case set-min-metric {
+          when "derived-from-or-self(../action, 'set-min-metric')";
+          choice minimun-metric-value {
+            description
+              "Mimimum metric to set or use";
+            case min-metric {
+              leaf min-metric {
+                type uint32 {
+                  range "0..4294967295";
+                }
+                description
+                  "Use the following mimumn metric value";
+              }
+            }
+          }
+        }
+
+        case set-max-metric {
+          when "derived-from-or-self(../action, 'set-max-metric')";
+          choice maximum-metric-value {
+            description
+              "Maximum metric to set or use";
+            case max-metric {
+              leaf max-metric {
+                type uint32 {
+                  range "0..4294967295";
+                }
+                description
+                  "Use the following maximum metric value";
+              }
+            }
+          }
+        }
         case set-tag {
           when "derived-from-or-self(../action, 'set-tag')";
           leaf tag {