From b19502d3b0d53c8c50e8e47124beb760b41e286d Mon Sep 17 00:00:00 2001 From: Yash Ranjan Date: Tue, 9 Feb 2021 20:53:46 -0800 Subject: [PATCH] ospf6d: Add CLI and logic for default-information originate command Signed-off-by: Yash Ranjan --- ospf6d/ospf6_asbr.c | 177 ++++++++++++++++++++++++++++++++++++++++++- ospf6d/ospf6_asbr.h | 1 + ospf6d/ospf6_top.c | 2 + ospf6d/ospf6_top.h | 16 +++- ospf6d/ospf6_zebra.c | 15 ++++ ospf6d/ospf6_zebra.h | 2 + ospf6d/subdir.am | 4 + 7 files changed, 214 insertions(+), 3 deletions(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 3497b26656..62ce74718b 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -57,6 +57,10 @@ static void ospf6_asbr_redistribute_set(int type, vrf_id_t vrf_id); static void ospf6_asbr_redistribute_unset(struct ospf6 *ospf6, struct ospf6_redist *red, int type); +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_asbr_clippy.c" +#endif + unsigned char conf_debug_ospf6_asbr = 0; #define ZROUTE_NAME(x) zebra_route_string(x) @@ -1150,7 +1154,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, if (!red) return; - if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id)) + if ((type != DEFAULT_ROUTE) + && !ospf6_zebra_is_redistribute(type, ospf6->vrf_id)) return; memset(&troute, 0, sizeof(troute)); @@ -1533,6 +1538,140 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6, vty_out(vty, "Total %d routes\n", total); } +static void ospf6_redistribute_default_set(struct ospf6 *ospf6, int originate) +{ + struct prefix_ipv6 p = {}; + struct in6_addr nexthop = {}; + int cur_originate = ospf6->default_originate; + + p.family = AF_INET6; + p.prefixlen = 0; + + ospf6->default_originate = originate; + + switch (cur_originate) { + case DEFAULT_ORIGINATE_NONE: + break; + case DEFAULT_ORIGINATE_ZEBRA: + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + zclient, AFI_IP6, ospf6->vrf_id); + ospf6_asbr_redistribute_remove(DEFAULT_ROUTE, 0, + (struct prefix *)&p, ospf6); + + break; + case DEFAULT_ORIGINATE_ALWAYS: + ospf6_asbr_redistribute_remove(DEFAULT_ROUTE, 0, + (struct prefix *)&p, ospf6); + break; + } + + switch (originate) { + case DEFAULT_ORIGINATE_NONE: + break; + case DEFAULT_ORIGINATE_ZEBRA: + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + zclient, AFI_IP6, ospf6->vrf_id); + + break; + case DEFAULT_ORIGINATE_ALWAYS: + ospf6_asbr_redistribute_add(DEFAULT_ROUTE, 0, + (struct prefix *)&p, 0, &nexthop, 0, + ospf6); + break; + } +} + +/* Default Route originate. */ +DEFPY (ospf6_default_route_originate, + ospf6_default_route_originate_cmd, + "default-information originate [{always$always|metric (0-16777214)$mval|metric-type (1-2)$mtype|route-map WORD$rtmap}]", + "Control distribution of default route\n" + "Distribute a default route\n" + "Always advertise default route\n" + "OSPFv3 default metric\n" + "OSPFv3 metric\n" + "OSPFv3 metric type for default routes\n" + "Set OSPFv3 External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + int default_originate = DEFAULT_ORIGINATE_ZEBRA; + struct ospf6_redist *red; + bool sameRtmap = false; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + int cur_originate = ospf6->default_originate; + + OSPF6_CMD_CHECK_RUNNING(ospf6); + + red = ospf6_redist_add(ospf6, DEFAULT_ROUTE, 0); + + if (always != NULL) + default_originate = DEFAULT_ORIGINATE_ALWAYS; + + if (mval_str == NULL) + mval = -1; + + if (mtype_str == NULL) + mtype = -1; + + /* To check ,if user is providing same route map */ + if ((rtmap == ROUTEMAP_NAME(red)) + || (rtmap && ROUTEMAP_NAME(red) + && (strcmp(rtmap, ROUTEMAP_NAME(red)) == 0))) + sameRtmap = true; + + /* Don't allow if the same lsa is aleardy originated. */ + if ((sameRtmap) && (red->dmetric.type == mtype) + && (red->dmetric.value == mval) + && (cur_originate == default_originate)) + return CMD_SUCCESS; + + /* Updating Metric details */ + red->dmetric.type = mtype; + red->dmetric.value = mval; + + /* updating route map details */ + if (rtmap) + ospf6_asbr_routemap_set(red, rtmap); + else + ospf6_asbr_routemap_unset(red); + + ospf6_redistribute_default_set(ospf6, default_originate); + return CMD_SUCCESS; +} + +DEFPY (no_ospf6_default_information_originate, + no_ospf6_default_information_originate_cmd, + "no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]", + NO_STR + "Control distribution of default information\n" + "Distribute a default route\n" + "Always advertise default route\n" + "OSPFv3 default metric\n" + "OSPFv3 metric\n" + "OSPFv3 metric type for default routes\n" + "Set OSPFv3 External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + struct ospf6_redist *red; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_CHECK_RUNNING(ospf6); + + red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0); + if (!red) + return CMD_SUCCESS; + + ospf6_asbr_routemap_unset(red); + ospf6_redist_del(ospf6, red, DEFAULT_ROUTE); + + ospf6_redistribute_default_set(ospf6, DEFAULT_ORIGINATE_NONE); + return CMD_SUCCESS; +} /* Routemap Functions */ static enum route_map_cmd_result_t @@ -2115,6 +2254,9 @@ void ospf6_asbr_init(void) install_element(VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd); + install_element(OSPF6_NODE, &ospf6_default_route_originate_cmd); + 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); @@ -2176,6 +2318,39 @@ int config_write_ospf6_debug_asbr(struct vty *vty) return 0; } +int ospf6_distribute_config_write(struct vty *vty, struct ospf6 *ospf6) +{ + struct ospf6_redist *red; + + if (ospf6) { + /* default-route print. */ + if (ospf6->default_originate != DEFAULT_ORIGINATE_NONE) { + vty_out(vty, " default-information originate"); + if (ospf6->default_originate + == DEFAULT_ORIGINATE_ALWAYS) + vty_out(vty, " always"); + + red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0); + if (red) { + if (red->dmetric.value >= 0) + vty_out(vty, " metric %d", + red->dmetric.value); + + if (red->dmetric.type >= 0) + vty_out(vty, " metric-type %d", + red->dmetric.type); + + if (ROUTEMAP_NAME(red)) + vty_out(vty, " route-map %s", + ROUTEMAP_NAME(red)); + } + + vty_out(vty, "\n"); + } + } + return 0; +} + void install_element_ospf6_debug_asbr(void) { install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd); diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index e4a4455a5c..4774ac435a 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -98,6 +98,7 @@ extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *); extern void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa); extern int config_write_ospf6_debug_asbr(struct vty *vty); +extern int ospf6_distribute_config_write(struct vty *vty, struct ospf6 *ospf6); extern void install_element_ospf6_debug_asbr(void); extern void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, struct ospf6_route *route, diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index a38f1cbc45..8be84ec2b4 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -247,6 +247,7 @@ static struct ospf6 *ospf6_create(const char *name) o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; o->spf_hold_multiplier = 1; + o->default_originate = DEFAULT_ORIGINATE_NONE; /* LSA timers value init */ o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL; @@ -1329,6 +1330,7 @@ static int config_write_ospf6(struct vty *vty) ospf6_area_config_write(vty, ospf6); ospf6_spf_config_write(vty, ospf6); ospf6_distance_config_write(vty, ospf6); + ospf6_distribute_config_write(vty, ospf6); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, j, oa)) { for (ALL_LIST_ELEMENTS_RO(oa->if_list, k, oi)) diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 7980659e68..eb683956e1 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -40,6 +40,15 @@ enum { struct ospf6_redist { uint8_t instance; + + /* Redistribute metric info. */ + struct { + int type; /* External metric type (E1 or E2). */ + int value; /* Value for static metric (24-bit). + * -1 means metric value is not set. + */ + } dmetric; + /* For redistribute route map. */ struct { char *name; @@ -83,13 +92,16 @@ struct ospf6 { uint32_t external_id; /* OSPF6 redistribute configuration */ - struct list *redist[ZEBRA_ROUTE_MAX]; + struct list *redist[ZEBRA_ROUTE_MAX + 1]; uint8_t flag; /* Configuration bitmask, refer to enum above */ uint8_t config_flags; - + int default_originate; /* Default information originate. */ +#define DEFAULT_ORIGINATE_NONE 0 +#define DEFAULT_ORIGINATE_ZEBRA 1 +#define DEFAULT_ORIGINATE_ALWAYS 2 /* LSA timer parameters */ unsigned int lsa_minarrival; /* LSA minimum arrival in milliseconds. */ diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 8d5e0f0a39..76e7172870 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -172,12 +172,23 @@ static int ospf6_zebra_if_address_update_delete(ZAPI_CALLBACK_ARGS) return 0; } +static int is_prefix_default(struct prefix_ipv6 *p) +{ + struct prefix_ipv6 q = {}; + + q.family = AF_INET6; + q.prefixlen = 0; + + return prefix_same((struct prefix *)p, (struct prefix *)&q); +} + static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS) { struct zapi_route api; unsigned long ifindex; struct in6_addr *nexthop; struct ospf6 *ospf6; + struct prefix_ipv6 p; ospf6 = ospf6_lookup_by_vrf_id(vrf_id); @@ -205,6 +216,10 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS) zebra_route_string(api.type), &api.prefix, nexthop, ifindex, api.tag); + memcpy(&p, &api.prefix, sizeof(p)); + if (is_prefix_default(&p)) + api.type = DEFAULT_ROUTE; + if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix, api.nexthop_num, nexthop, api.tag, diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h index 5f340924b9..a3ccc3d38d 100644 --- a/ospf6d/ospf6_zebra.h +++ b/ospf6d/ospf6_zebra.h @@ -23,6 +23,8 @@ #include "zclient.h" +#define DEFAULT_ROUTE ZEBRA_ROUTE_MAX + /* Debug option */ extern unsigned char conf_debug_ospf6_zebra; #define OSPF6_DEBUG_ZEBRA_SEND 0x01 diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index 82d880cca8..dc173da9dc 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -81,3 +81,7 @@ ospf6d_ospf6d_snmp_la_SOURCES = ospf6d/ospf6_snmp.c ospf6d_ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11 ospf6d_ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la + +clippy_scan += \ + ospf6d/ospf6_asbr.c \ + # end