]> git.proxmox.com Git - mirror_frr.git/commitdiff
ospf6d: add support for route tags
authorChristian Franke <chris@opensourcerouting.org>
Sat, 1 Oct 2016 04:41:40 +0000 (06:41 +0200)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Sat, 8 Oct 2016 01:05:05 +0000 (21:05 -0400)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
ospf6d/ospf6_asbr.c
ospf6d/ospf6_asbr.h
ospf6d/ospf6_route.h
ospf6d/ospf6_zebra.c

index 208d3b8c4c54d39b020eebbfbd1a5e846240fca5..09e6420ffe16972261cf3ed2461d90cbb6b50b11 100644 (file)
@@ -93,7 +93,10 @@ ospf6_as_external_lsa_originate (struct ospf6_route *route)
     UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
 
   /* external route tag */
-  UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
+  if (info->tag)
+    SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
+  else
+    UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
 
   /* Set metric */
   OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
@@ -123,7 +126,10 @@ ospf6_as_external_lsa_originate (struct ospf6_route *route)
   /* External Route Tag */
   if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
     {
-      /* xxx */
+      route_tag_t network_order = htonl(info->tag);
+
+      memcpy (p, &network_order, sizeof(network_order));
+      p += sizeof(network_order);
     }
 
   /* Fill LSA Header */
@@ -146,6 +152,29 @@ ospf6_as_external_lsa_originate (struct ospf6_route *route)
   ospf6_lsa_originate_process (lsa, ospf6);
 }
 
+static route_tag_t
+ospf6_as_external_lsa_get_tag (struct ospf6_lsa *lsa)
+{
+  struct ospf6_as_external_lsa *external;
+  ptrdiff_t tag_offset;
+  route_tag_t network_order;
+
+  if (!lsa)
+    return 0;
+
+  external = (struct ospf6_as_external_lsa *)
+    OSPF6_LSA_HEADER_END (lsa->header);
+
+  if (!CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
+    return 0;
+
+  tag_offset = sizeof(*external) + OSPF6_PREFIX_SPACE(external->prefix.prefix_length);
+  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
+    tag_offset += sizeof(struct in6_addr);
+
+  memcpy(&network_order, (caddr_t)external + tag_offset, sizeof(network_order));
+  return ntohl(network_order);
+}
 
 void
 ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
@@ -222,6 +251,8 @@ ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
       route->path.u.cost_e2 = 0;
     }
 
+  route->path.tag = ospf6_as_external_lsa_get_tag (lsa);
+
   ospf6_route_copy_nexthops (route, asbr_entry);
 
   if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
@@ -427,7 +458,7 @@ ospf6_asbr_send_externals_to_area (struct ospf6_area *oa)
 
 void
 ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
-                             u_int nexthop_num, struct in6_addr *nexthop)
+                             u_int nexthop_num, struct in6_addr *nexthop, route_tag_t tag)
 {
   int ret;
   struct ospf6_route troute;
@@ -469,6 +500,7 @@ ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
       memset (&tinfo, 0, sizeof (tinfo));
       troute.route_option = &tinfo;
       tinfo.ifindex = ifindex;
+      tinfo.tag = tag;
 
       ret = route_map_apply (ospf6->rmap[type].map, prefix,
                              RMAP_OSPF6, &troute);
@@ -495,6 +527,12 @@ ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
           if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
             memcpy (&info->forwarding, &tinfo.forwarding,
                     sizeof (struct in6_addr));
+          info->tag = tinfo.tag;
+        }
+      else
+        {
+          /* If there is no route-map, simply update the tag */
+          info->tag = tag;
         }
 
       info->type = type;
@@ -542,6 +580,12 @@ ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix,
       if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
         memcpy (&info->forwarding, &tinfo.forwarding,
                 sizeof (struct in6_addr));
+      info->tag = tinfo.tag;
+    }
+  else
+    {
+      /* If there is no route-map, simply set the tag */
+      info->tag = tag;
     }
 
   info->type = type;
@@ -861,6 +905,30 @@ ospf6_routemap_rule_match_interface_cmd =
   ospf6_routemap_rule_match_interface_free
 };
 
+/* Match function for matching route tags */
+static route_map_result_t
+ospf6_routemap_rule_match_tag (void *rule, struct prefix *prefix,
+                               route_map_object_t type, void *object)
+{
+  route_tag_t *tag = rule;
+  struct ospf6_route *route = object;
+  struct ospf6_external_info *info = route->route_option;
+
+  if (type == RMAP_OSPF6 && info->tag == *tag)
+    return RMAP_MATCH;
+
+  return RMAP_NOMATCH;
+}
+
+static struct route_map_rule_cmd
+ospf6_routemap_rule_match_tag_cmd =
+{
+  "tag",
+  ospf6_routemap_rule_match_tag,
+  route_map_rule_tag_compile,
+  route_map_rule_tag_free,
+};
+
 static route_map_result_t
 ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
                                      route_map_object_t type, void *object)
@@ -986,6 +1054,30 @@ ospf6_routemap_rule_set_forwarding_cmd =
   ospf6_routemap_rule_set_forwarding_free,
 };
 
+static route_map_result_t
+ospf6_routemap_rule_set_tag (void *rule, struct prefix *prefix,
+                             route_map_object_t type, void *object)
+{
+  route_tag_t *tag = rule;
+  struct ospf6_route *route = object;
+  struct ospf6_external_info *info = route->route_option;
+
+  if (type != RMAP_OSPF6)
+    return RMAP_OKAY;
+
+  info->tag = *tag;
+  return RMAP_OKAY;
+}
+
+static struct route_map_rule_cmd
+ospf6_routemap_rule_set_tag_cmd =
+{
+  "tag",
+  ospf6_routemap_rule_set_tag,
+  route_map_rule_tag_compile,
+  route_map_rule_tag_free,
+};
+
 static int
 route_map_command_status (struct vty *vty, int ret)
 {
@@ -1054,8 +1146,8 @@ DEFUN (ospf6_routemap_match_interface,
 DEFUN (ospf6_routemap_no_match_interface,
        ospf6_routemap_no_match_interface_cmd,
        "no match interface",
-       MATCH_STR
        NO_STR
+       MATCH_STR
        "Match first hop interface of route\n")
 {
   int ret = route_map_delete_match ((struct route_map_index *) vty->index,
@@ -1066,11 +1158,45 @@ DEFUN (ospf6_routemap_no_match_interface,
 ALIAS (ospf6_routemap_no_match_interface,
        ospf6_routemap_no_match_interface_val_cmd,
        "no match interface WORD",
-       MATCH_STR
        NO_STR
+       MATCH_STR
        "Match first hop interface of route\n"
        "Interface name\n")
 
+/* add "match tag" */
+DEFUN (ospf6_routemap_match_tag,
+       ospf6_routemap_match_tag_cmd,
+       "match tag <1-4294967295>",
+       MATCH_STR
+       "Tag value for routing protocol\n"
+       "Tag value\n")
+{
+  int ret = route_map_add_match ((struct route_map_index *) vty->index,
+                               "tag", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "match tag" */
+DEFUN (ospf6_routemap_no_match_tag,
+       ospf6_routemap_no_match_tag_cmd,
+       "no match tag",
+       NO_STR
+       MATCH_STR
+       "Tag value for routing protocol\n")
+{
+  int ret = route_map_delete_match ((struct route_map_index *) vty->index,
+                                  "tag", argc ? argv[0] : NULL);
+  return route_map_command_status (vty, ret);
+}
+
+ALIAS (ospf6_routemap_no_match_tag,
+       ospf6_routemap_no_match_tag_val_cmd,
+       "no match tag <1-4294967295>",
+       NO_STR
+       MATCH_STR
+       "Tag value for routing protocol\n"
+       "Tag value\n")
+
 /* add "set metric-type" */
 DEFUN (ospf6_routemap_set_metric_type,
        ospf6_routemap_set_metric_type_cmd,
@@ -1167,6 +1293,40 @@ DEFUN (ospf6_routemap_no_set_forwarding,
   return route_map_command_status (vty, ret);
 }
 
+/* add "set tag" */
+DEFUN (ospf6_routemap_set_tag,
+       ospf6_routemap_set_tag_cmd,
+       "set tag <1-4294967295>",
+       "Set value\n"
+       "Tag value for routing protocol\n"
+       "Tag value\n")
+{
+  int ret = route_map_add_set ((struct route_map_index *) vty->index,
+                               "tag", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "set tag" */
+DEFUN (ospf6_routemap_no_set_tag,
+       ospf6_routemap_no_set_tag_cmd,
+       "no set tag",
+       NO_STR
+       "Set value\n"
+       "Tag value for routing protocol\n")
+{
+  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+                                  "tag", argc ? argv[0] : NULL);
+  return route_map_command_status (vty, ret);
+}
+
+ALIAS (ospf6_routemap_no_set_tag,
+       ospf6_routemap_no_set_tag_val_cmd,
+       "no set tag <1-4294967295>",
+       NO_STR
+       "Set value\n"
+       "Tag value for routing protocol\n"
+       "Tag value\n")
+
 static void
 ospf6_routemap_init (void)
 {
@@ -1177,10 +1337,12 @@ ospf6_routemap_init (void)
 
   route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
   route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
+  route_map_install_match (&ospf6_routemap_rule_match_tag_cmd);
 
   route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
   route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
   route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
+  route_map_install_set (&ospf6_routemap_rule_set_tag_cmd);
 
   /* Match address prefix-list */
   install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
@@ -1191,6 +1353,11 @@ ospf6_routemap_init (void)
   install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
   install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
 
+  /* Match tag */
+  install_element (RMAP_NODE, &ospf6_routemap_match_tag_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_match_tag_val_cmd);
+
   /* ASE Metric Type (e.g. Type-1/Type-2) */
   install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
   install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
@@ -1200,9 +1367,14 @@ ospf6_routemap_init (void)
   install_element (RMAP_NODE, &no_set_metric_cmd);
   install_element (RMAP_NODE, &no_set_metric_val_cmd);
 
-  /* ASE Metric */
+  /* Forwarding address */
   install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
   install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
+
+  /* Tag */
+  install_element (RMAP_NODE, &ospf6_routemap_set_tag_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_set_tag_val_cmd);
 }
 
 
@@ -1280,6 +1452,13 @@ ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
               VNL);
     }
 
+  /* Tag */
+  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
+    {
+      vty_out (vty, "     Tag: %"ROUTE_TAG_PRI"%s",
+               ospf6_as_external_lsa_get_tag (lsa), VNL);
+    }
+
   return 0;
 }
 
index 645e8fd9cf2bb00fa752ef46c324cb4ccc92b268..da6bbdd9c3645807b4a44133baadf0e264745cb7 100644 (file)
@@ -47,7 +47,8 @@ struct ospf6_external_info
   u_int32_t id;
 
   struct in6_addr forwarding;
-  /* u_int32_t tag; */
+
+  route_tag_t tag;
 
   ifindex_t ifindex;
 };
@@ -82,7 +83,8 @@ extern int ospf6_asbr_is_asbr (struct ospf6 *o);
 extern void ospf6_asbr_redistribute_add (int type, ifindex_t ifindex,
                                          struct prefix *prefix,
                                          u_int nexthop_num,
-                                         struct in6_addr *nexthop);
+                                         struct in6_addr *nexthop,
+                                         route_tag_t tag);
 extern void ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex,
                                             struct prefix *prefix);
 
index 610b0970b0ea707f1f35534a85cb1aea0a610438..7ecc066602a2aad6a8c687c046d75589e49d4381 100644 (file)
@@ -100,6 +100,7 @@ struct ospf6_path
     u_int32_t cost_e2;
     u_int32_t cost_config;
   } u;
+  u_int32_t tag;
 };
 
 #define OSPF6_PATH_TYPE_NONE         0
index 45165fdf2e36e203f68a1db9171bfe3a853258f7..d24b808aaad89c2e61669d8830876c2d57a83a45 100644 (file)
@@ -260,6 +260,11 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
   else
     api.metric = 0;
 
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
+    api.tag = stream_getl (s);
+  else
+    api.tag = 0;
+
   if (IS_OSPF6_DEBUG_ZEBRA (RECV))
     {
       char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
@@ -269,14 +274,14 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
       else
         snprintf (nexthopstr, sizeof (nexthopstr), "::");
 
-      zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld",
+      zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %"ROUTE_TAG_PRI,
                  (command == ZEBRA_IPV6_ROUTE_ADD ? "add" : "delete"),
-                 zebra_route_string(api.type), prefixstr, nexthopstr, ifindex);
+                 zebra_route_string(api.type), prefixstr, nexthopstr, ifindex, api.tag);
     }
  
   if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
     ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p,
-                                 api.nexthop_num, nexthop);
+                                 api.nexthop_num, nexthop, api.tag);
   else
     ospf6_asbr_redistribute_remove (api.type, ifindex, (struct prefix *) &p);
 
@@ -468,6 +473,11 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request)
   SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
   api.metric = (request->path.metric_type == 2 ?
                 request->path.u.cost_e2 : request->path.cost);
+  if (request->path.tag)
+    {
+      SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
+      api.tag = request->path.tag;
+    }
 
   dest = (struct prefix_ipv6 *) &request->prefix;
   if (type == REM)