ospf6d: add support for route tags
[ported by Paul Jakma, paul@jakma.org]
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 4b7d214..a442506 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -93,7 +93,10 @@
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 @@
/* 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_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)
@@ -223,6 +252,8 @@
route->path.cost_e2 = 0;
}
+ route->path.tag = ospf6_as_external_lsa_get_tag (lsa);
+
for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
@@ -413,7 +444,7 @@
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;
@@ -455,6 +486,7 @@
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);
@@ -481,6 +513,12 @@
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;
@@ -526,6 +564,12 @@
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;
@@ -844,6 +888,30 @@
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)
@@ -969,6 +1037,30 @@
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)
{
@@ -1037,8 +1129,8 @@
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,
@@ -1049,11 +1141,45 @@
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,
@@ -1150,6 +1276,40 @@
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)
{
@@ -1160,10 +1320,12 @@
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);
@@ -1174,6 +1336,11 @@
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);
@@ -1183,9 +1350,14 @@
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);
}
@@ -1263,6 +1435,13 @@
VNL);
}
+ /* Tag */
+ if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
+ {
+ vty_out (vty, " Tag: %u%s",
+ ospf6_as_external_lsa_get_tag (lsa), VNL);
+ }
+
return 0;
}
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index f3df90b..14113b0 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -47,7 +47,8 @@
u_int32_t id;
struct in6_addr forwarding;
- /* u_int32_t tag; */
+
+ route_tag_t tag;
ifindex_t ifindex;
};
@@ -82,7 +83,8 @@
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);
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 2fb2c1d..027a648 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -97,6 +97,7 @@
u_int8_t metric_type;
u_int32_t cost;
u_int32_t cost_e2;
+ u_int32_t tag;
};
#define OSPF6_PATH_TYPE_NONE 0
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index f80bb23..2976214 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -247,6 +247,11 @@
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[128], nexthopstr[128];
@@ -256,14 +261,14 @@
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 %u",
(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_IPV6_ROUTE_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);
@@ -470,9 +475,12 @@
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = (request->path.metric_type == 2 ?
request->path.cost_e2 : request->path.cost);
- SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
- api.distance = ospf6_distance_apply (request, ospf6);
-
+ 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)
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, &api);