--- embedaddon/quagga/ripd/rip_zebra.c 2012/10/09 09:22:29 1.1.1.2 +++ embedaddon/quagga/ripd/rip_zebra.c 2016/11/02 10:09:10 1.1.1.3 @@ -23,84 +23,120 @@ #include "command.h" #include "prefix.h" +#include "table.h" #include "stream.h" +#include "memory.h" #include "routemap.h" #include "zclient.h" #include "log.h" +#include "vrf.h" #include "ripd/ripd.h" #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" /* All information about zebra. */ struct zclient *zclient = NULL; - -/* RIPd to zebra command interface. */ -void -rip_zebra_ipv4_add (struct prefix_ipv4 *p, struct in_addr *nexthop, - u_int32_t metric, u_char distance) + +/* Send ECMP routes to zebra. */ +static void +rip_zebra_ipv4_send (struct route_node *rp, u_char cmd) { + static struct in_addr **nexthops = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; struct zapi_ipv4 api; + struct listnode *listnode = NULL; + struct rip_info *rinfo = NULL; + int count = 0; - if (zclient->redist[ZEBRA_ROUTE_RIP]) + if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_RIP], VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIP; api.flags = 0; api.message = 0; api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount (list)) + { + nexthops_len = listcount (list); + nexthops = XREALLOC (MTYPE_TMP, nexthops, + nexthops_len * sizeof (struct in_addr *)); + } + SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + nexthops[count++] = &rinfo->nexthop; + if (cmd == ZEBRA_IPV4_ROUTE_ADD) + SET_FLAG (rinfo->flags, RIP_RTF_FIB); + else + UNSET_FLAG (rinfo->flags, RIP_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; api.ifindex_num = 0; + + rinfo = listgetdata (listhead (list)); + SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; + api.metric = rinfo->metric; - if (distance && distance != ZEBRA_RIP_DISTANCE_DEFAULT) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } + if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) + { + SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = rinfo->distance; + } - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + zapi_ipv4_route (cmd, zclient, + (struct prefix_ipv4 *)&rp->p, &api); + if (IS_RIP_DEBUG_ZEBRA) + { + if (rip->ecmp) + zlog_debug ("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ + "Install into zebra" : "Delete from zebra", + inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen, count); + else + zlog_debug ("%s: %s/%d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ + "Install into zebra" : "Delete from zebra", + inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); + } + rip_global_route_changes++; } } +/* Add/update ECMP routes to zebra. */ void -rip_zebra_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *nexthop, - u_int32_t metric) +rip_zebra_ipv4_add (struct route_node *rp) { - struct zapi_ipv4 api; + rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_ADD); +} - if (zclient->redist[ZEBRA_ROUTE_RIP]) - { - api.type = ZEBRA_ROUTE_RIP; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); - - rip_global_route_changes++; - } +/* Delete ECMP routes from zebra. */ +void +rip_zebra_ipv4_delete (struct route_node *rp) +{ + rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ static int -rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) +rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { struct stream *s; struct zapi_ipv4 api; unsigned long ifindex; struct in_addr nexthop; struct prefix_ipv4 p; - + unsigned char plength = 0; + s = zclient->ibuf; ifindex = 0; nexthop.s_addr = 0; @@ -113,7 +149,8 @@ rip_zebra_read_ipv4 (int command, struct zclient *zcli /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; - p.prefixlen = stream_getc (s); + plength = stream_getc (s); + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ @@ -196,7 +233,7 @@ rip_routemap_unset (int type, const char *name) return 0; } - + /* Redistribution types */ static struct { int type; @@ -240,10 +277,10 @@ DEFUN (no_router_zebra, static int rip_redistribute_set (int type) { - if (zclient->redist[type]) + if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)) return CMD_SUCCESS; - zclient->redist[type] = 1; + vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT); if (zclient->sock > 0) zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type); @@ -255,13 +292,14 @@ rip_redistribute_set (int type) static int rip_redistribute_unset (int type) { - if (! zclient->redist[type]) + if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)) return CMD_SUCCESS; - zclient->redist[type] = 0; + vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT); if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); + zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, + VRF_DEFAULT); /* Remove the routes from RIP table. */ rip_redistribute_withdraw (type); @@ -272,7 +310,7 @@ rip_redistribute_unset (int type) int rip_redistribute_check (int type) { - return (zclient->redist[type]); + return vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT); } void @@ -282,13 +320,14 @@ rip_redistribute_clean (void) for (i = 0; redist_type[i].str; i++) { - if (zclient->redist[redist_type[i].type]) + if (vrf_bitmap_check (zclient->redist[redist_type[i].type], VRF_DEFAULT)) { if (zclient->sock > 0) zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, - zclient, redist_type[i].type); + zclient, redist_type[i].type, + VRF_DEFAULT); - zclient->redist[redist_type[i].type] = 0; + vrf_bitmap_unset (zclient->redist[redist_type[i].type], VRF_DEFAULT); /* Remove the routes from RIP table. */ rip_redistribute_withdraw (redist_type[i].type); @@ -302,7 +341,7 @@ DEFUN (rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - zclient->redist[ZEBRA_ROUTE_RIP] = 1; + vrf_bitmap_set (zclient->redist[ZEBRA_ROUTE_RIP], VRF_DEFAULT); return CMD_SUCCESS; } @@ -313,7 +352,7 @@ DEFUN (no_rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - zclient->redist[ZEBRA_ROUTE_RIP] = 0; + vrf_bitmap_unset (zclient->redist[ZEBRA_ROUTE_RIP], VRF_DEFAULT); return CMD_SUCCESS; } @@ -331,7 +370,7 @@ DEFUN (rip_redistribute_type, redist_type[i].str_min_len) == 0) { zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, - redist_type[i].type); + redist_type[i].type, VRF_DEFAULT); return CMD_SUCCESS; } } @@ -384,7 +423,8 @@ DEFUN (rip_redistribute_type_routemap, redist_type[i].str_min_len) == 0) { rip_routemap_set (redist_type[i].type, argv[1]); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type); + zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type, + VRF_DEFAULT); return CMD_SUCCESS; } } @@ -442,7 +482,8 @@ DEFUN (rip_redistribute_type_metric, redist_type[i].str_min_len) == 0) { rip_redistribute_metric_set (redist_type[i].type, metric); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type); + zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type, + VRF_DEFAULT); return CMD_SUCCESS; } } @@ -503,7 +544,8 @@ DEFUN (rip_redistribute_type_metric_routemap, { rip_redistribute_metric_set (redist_type[i].type, metric); rip_routemap_set (redist_type[i].type, argv[2]); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type); + zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, redist_type[i].type, + VRF_DEFAULT); return CMD_SUCCESS; } } @@ -551,7 +593,7 @@ DEFUN (no_rip_redistribute_type_metric_routemap, return CMD_WARNING; } - + /* Default information originate. */ DEFUN (rip_default_information_originate, @@ -597,7 +639,7 @@ DEFUN (no_rip_default_information_originate, return CMD_SUCCESS; } - + /* RIP configuration write function. */ static int config_write_zebra (struct vty *vty) @@ -607,7 +649,7 @@ config_write_zebra (struct vty *vty) vty_out (vty, "no router zebra%s", VTY_NEWLINE); return 1; } - else if (! zclient->redist[ZEBRA_ROUTE_RIP]) + else if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_RIP], VRF_DEFAULT)) { vty_out (vty, "router zebra%s", VTY_NEWLINE); vty_out (vty, " no redistribute rip%s", VTY_NEWLINE); @@ -622,7 +664,8 @@ config_write_rip_redistribute (struct vty *vty, int co int i; for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && zclient->redist[i]) + if (i != zclient->redist_default && + vrf_bitmap_check (zclient->redist[i], VRF_DEFAULT)) { if (config_mode) { @@ -662,12 +705,19 @@ static struct cmd_node zebra_node = "%s(config-router)# ", }; +static void +rip_zebra_connected (struct zclient *zclient) +{ + zclient_send_requests (zclient, VRF_DEFAULT); +} + void -rip_zclient_init () +rip_zclient_init (struct thread_master *master) { /* Set default value to the zebra client structure. */ - zclient = zclient_new (); + zclient = zclient_new (master); zclient_init (zclient, ZEBRA_ROUTE_RIP); + zclient->zebra_connected = rip_zebra_connected; zclient->interface_add = rip_interface_add; zclient->interface_delete = rip_interface_delete; zclient->interface_address_add = rip_interface_address_add;