From 464015fa32f89e7f128cb19917c9e347b3284d69 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sat, 1 Oct 2016 06:41:40 +0200 Subject: [PATCH] ospf6d: add support for route tags Signed-off-by: Christian Franke --- ospf6d/ospf6_asbr.c | 191 +++++++++++++++++++++++++++++++++++++++++-- ospf6d/ospf6_asbr.h | 6 +- ospf6d/ospf6_route.h | 1 + ospf6d/ospf6_zebra.c | 16 +++- 4 files changed, 203 insertions(+), 11 deletions(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 208d3b8c4c..09e6420ffe 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -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; } diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index 645e8fd9cf..da6bbdd9c3 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -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); diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 610b0970b0..7ecc066602 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -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 diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 45165fdf2e..d24b808aaa 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -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) -- 2.39.5