--- embedaddon/quagga/zebra/zserv.c 2013/07/21 23:54:41 1.1.1.3 +++ embedaddon/quagga/zebra/zserv.c 2016/11/02 10:09:10 1.1.1.4 @@ -36,13 +36,14 @@ #include "privs.h" #include "network.h" #include "buffer.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/router-id.h" #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/ipforward.h" - + /* Event list of zebra. */ enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; @@ -51,7 +52,7 @@ extern struct zebra_t zebrad; static void zebra_event (enum event event, int sock, struct zserv *client); extern struct zebra_privs_t zserv_privs; - + static void zebra_client_close (struct zserv *client); static int @@ -131,12 +132,13 @@ zebra_server_send_message(struct zserv *client) } static void -zserv_create_header (struct stream *s, uint16_t cmd) +zserv_create_header (struct stream *s, uint16_t cmd, vrf_id_t vrf_id) { /* length placeholder, caller can update */ stream_putw (s, ZEBRA_HEADER_SIZE); stream_putc (s, ZEBRA_HEADER_MARKER); stream_putc (s, ZSERV_VERSION); + stream_putw (s, vrf_id); stream_putw (s, cmd); } @@ -152,13 +154,10 @@ zserv_encode_interface (struct stream *s, struct inter stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); -#ifdef HAVE_STRUCT_SOCKADDR_DL - stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage)); -#else + stream_putl (s, ifp->ll_type); stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -181,13 +180,13 @@ zsend_interface_add (struct zserv *client, struct inte struct stream *s; /* Check this client need interface information. */ - if (! client->ifinfo) + if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) return 0; s = client->obuf; stream_reset (s); - zserv_create_header (s, ZEBRA_INTERFACE_ADD); + zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); zserv_encode_interface (s, ifp); return zebra_server_send_message(client); @@ -200,13 +199,13 @@ zsend_interface_delete (struct zserv *client, struct i struct stream *s; /* Check this client need interface information. */ - if (! client->ifinfo) + if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) return 0; s = client->obuf; stream_reset (s); - zserv_create_header (s, ZEBRA_INTERFACE_DELETE); + zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); zserv_encode_interface (s, ifp); return zebra_server_send_message (client); @@ -259,13 +258,13 @@ zsend_interface_address (int cmd, struct zserv *client struct prefix *p; /* Check this client need interface information. */ - if (! client->ifinfo) + if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) return 0; s = client->obuf; stream_reset (s); - zserv_create_header (s, cmd); + zserv_create_header (s, cmd, ifp->vrf_id); stream_putl (s, ifp->ifindex); /* Interface address flag. */ @@ -313,13 +312,13 @@ zsend_interface_update (int cmd, struct zserv *client, struct stream *s; /* Check this client need interface information. */ - if (! client->ifinfo) + if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id)) return 0; s = client->obuf; stream_reset (s); - zserv_create_header (s, cmd); + zserv_create_header (s, cmd, ifp->vrf_id); zserv_encode_interface (s, ifp); return zebra_server_send_message(client); @@ -358,11 +357,17 @@ zsend_route_multipath (int cmd, struct zserv *client, unsigned long nhnummark = 0, messmark = 0; int nhnum = 0; u_char zapi_flags = 0; - + + /* Check this client need this route. */ + if (!vrf_bitmap_check (client->redist[rib->type], rib->vrf_id) && + !(is_default (p) && + vrf_bitmap_check (client->redist_default, rib->vrf_id))) + return 0; + s = client->obuf; stream_reset (s); - zserv_create_header (s, cmd); + zserv_create_header (s, cmd, rib->vrf_id); /* Put type and nexthop. */ stream_putc (s, rib->type); @@ -389,7 +394,7 @@ zsend_route_multipath (int cmd, struct zserv *client, for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); @@ -446,6 +451,8 @@ zsend_route_multipath (int cmd, struct zserv *client, stream_putc (s, rib->distance); SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC); stream_putl (s, rib->metric); + SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU); + stream_putl (s, rib->mtu); } /* write real message flags value */ @@ -463,7 +470,8 @@ zsend_route_multipath (int cmd, struct zserv *client, #ifdef HAVE_IPV6 static int -zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr) +zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr, + vrf_id_t vrf_id) { struct stream *s; struct rib *rib; @@ -472,15 +480,15 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struc struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv6 (addr); + rib = rib_match_ipv6 (addr, vrf_id); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP); - stream_put (s, &addr, 16); + zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, vrf_id); + stream_put (s, addr, 16); if (rib) { @@ -488,8 +496,11 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struc num = 0; nump = stream_get_endp(s); stream_putc (s, 0); + /* Only non-recursive routes are elegible to resolve nexthop we + * are looking up. Therefore, we will just iterate over the top + * chain of nexthops. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { stream_putc (s, nexthop->type); switch (nexthop->type) @@ -527,7 +538,8 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struc #endif /* HAVE_IPV6 */ static int -zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr) +zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr, + vrf_id_t vrf_id) { struct stream *s; struct rib *rib; @@ -535,25 +547,30 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struc u_char num; struct nexthop *nexthop; - /* Lookup nexthop. */ - rib = rib_match_ipv4 (addr); + /* Lookup nexthop - eBGP excluded */ + rib = rib_match_ipv4_safi (addr, SAFI_UNICAST, 1, NULL, vrf_id); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP); + zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id); stream_put_in_addr (s, &addr); if (rib) { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Matching rib entry found.", __func__); stream_putl (s, rib->metric); num = 0; nump = stream_get_endp(s); stream_putc (s, 0); + /* Only non-recursive routes are elegible to resolve the nexthop we + * are looking up. Therefore, we will just iterate over the top + * chain of nexthops. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { stream_putc (s, nexthop->type); switch (nexthop->type) @@ -561,6 +578,10 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struc case ZEBRA_NEXTHOP_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + stream_put_in_addr (s, &nexthop->gate.ipv4); + stream_putl (s, nexthop->ifindex); + break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: stream_putl (s, nexthop->ifindex); @@ -575,6 +596,8 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struc } else { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: No matching rib entry found.", __func__); stream_putl (s, 0); stream_putc (s, 0); } @@ -584,24 +607,95 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struc return zebra_server_send_message(client); } +/* + Modified version of zsend_ipv4_nexthop_lookup(): + Query unicast rib if nexthop is not found on mrib. + Returns both route metric and protocol distance. +*/ static int -zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) +zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, + struct rib *rib) { struct stream *s; + unsigned long nump; + u_char num; + struct nexthop *nexthop; + + /* Get output stream. */ + s = client->obuf; + stream_reset (s); + + /* Fill in result. */ + zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, rib->vrf_id); + stream_put_in_addr (s, &addr); + + if (rib) + { + stream_putc (s, rib->distance); + stream_putl (s, rib->metric); + num = 0; + nump = stream_get_endp(s); /* remember position for nexthop_num */ + stream_putc (s, 0); /* reserve room for nexthop_num */ + /* Only non-recursive routes are elegible to resolve the nexthop we + * are looking up. Therefore, we will just iterate over the top + * chain of nexthops. */ + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + { + stream_putc (s, nexthop->type); + switch (nexthop->type) + { + case ZEBRA_NEXTHOP_IPV4: + stream_put_in_addr (s, &nexthop->gate.ipv4); + break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + stream_put_in_addr (s, &nexthop->gate.ipv4); + stream_putl (s, nexthop->ifindex); + break; + case ZEBRA_NEXTHOP_IFINDEX: + case ZEBRA_NEXTHOP_IFNAME: + stream_putl (s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + num++; + } + + stream_putc_at (s, nump, num); /* store nexthop_num */ + } + else + { + stream_putc (s, 0); /* distance */ + stream_putl (s, 0); /* metric */ + stream_putc (s, 0); /* nexthop_num */ + } + + stream_putw_at (s, 0, stream_get_endp (s)); + + return zebra_server_send_message(client); +} + +static int +zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p, + vrf_id_t vrf_id) +{ + struct stream *s; struct rib *rib; unsigned long nump; u_char num; struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_lookup_ipv4 (p); + rib = rib_lookup_ipv4 (p, vrf_id); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP); + zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP, vrf_id); stream_put_in_addr (s, &p->prefix); if (rib) @@ -611,7 +705,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct nump = stream_get_endp(s); stream_putc (s, 0); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { stream_putc (s, nexthop->type); switch (nexthop->type) @@ -619,6 +713,10 @@ zsend_ipv4_import_lookup (struct zserv *client, struct case ZEBRA_NEXTHOP_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + stream_put_in_addr (s, &nexthop->gate.ipv4); + stream_putl (s, nexthop->ifindex); + break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: stream_putl (s, nexthop->ifindex); @@ -641,23 +739,24 @@ zsend_ipv4_import_lookup (struct zserv *client, struct return zebra_server_send_message(client); } - + /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ int -zsend_router_id_update (struct zserv *client, struct prefix *p) +zsend_router_id_update (struct zserv *client, struct prefix *p, + vrf_id_t vrf_id) { struct stream *s; int blen; /* Check this client need interface information. */ - if (!client->ridinfo) + if (! vrf_bitmap_check (client->ridinfo, vrf_id)) return 0; s = client->obuf; stream_reset (s); /* Message type. */ - zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE); + zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); /* Prefix information. */ stream_putc (s, p->family); @@ -670,11 +769,11 @@ zsend_router_id_update (struct zserv *client, struct p return zebra_server_send_message(client); } - + /* Register zebra server interface information. Send current all interface and address information. */ static int -zread_interface_add (struct zserv *client, u_short length) +zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id) { struct listnode *ifnode, *ifnnode; struct listnode *cnode, *cnnode; @@ -682,9 +781,9 @@ zread_interface_add (struct zserv *client, u_short len struct connected *c; /* Interface information is needed. */ - client->ifinfo = 1; + vrf_bitmap_set (client->ifinfo, vrf_id); - for (ALL_LIST_ELEMENTS (iflist, ifnode, ifnnode, ifp)) + for (ALL_LIST_ELEMENTS (vrf_iflist (vrf_id), ifnode, ifnnode, ifp)) { /* Skip pseudo interface. */ if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) @@ -706,9 +805,9 @@ zread_interface_add (struct zserv *client, u_short len /* Unregister zebra server interface information. */ static int -zread_interface_delete (struct zserv *client, u_short length) +zread_interface_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) { - client->ifinfo = 0; + vrf_bitmap_unset (client->ifinfo, vrf_id); return 0; } @@ -718,7 +817,7 @@ zread_interface_delete (struct zserv *client, u_short * add kernel route. */ static int -zread_ipv4_add (struct zserv *client, u_short length) +zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id) { int i; struct rib *rib; @@ -728,7 +827,7 @@ zread_ipv4_add (struct zserv *client, u_short length) u_char nexthop_num; u_char nexthop_type; struct stream *s; - unsigned int ifindex; + ifindex_t ifindex; u_char ifname_len; safi_t safi; @@ -752,6 +851,9 @@ zread_ipv4_add (struct zserv *client, u_short length) p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + /* VRF ID */ + rib->vrf_id = vrf_id; + /* Nexthop parse. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { @@ -798,6 +900,9 @@ zread_ipv4_add (struct zserv *client, u_short length) if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) rib->metric = stream_getl (s); + if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) + rib->mtu = stream_getl (s); + /* Table */ rib->table=zebrad.rtm_table_default; rib_add_ipv4_multipath (&p, rib, safi); @@ -806,7 +911,7 @@ zread_ipv4_add (struct zserv *client, u_short length) /* Zebra server IPv4 prefix delete function. */ static int -zread_ipv4_delete (struct zserv *client, u_short length) +zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) { int i; struct stream *s; @@ -859,6 +964,7 @@ zread_ipv4_delete (struct zserv *client, u_short lengt break; case ZEBRA_NEXTHOP_IPV4_IFINDEX: nexthop.s_addr = stream_get_ipv4 (s); + nexthop_p = &nexthop; ifindex = stream_getl (s); break; case ZEBRA_NEXTHOP_IPV6: @@ -881,23 +987,42 @@ zread_ipv4_delete (struct zserv *client, u_short lengt api.metric = 0; rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex, - client->rtm_table, api.safi); + vrf_id, api.safi); return 0; } /* Nexthop lookup for IPv4. */ static int -zread_ipv4_nexthop_lookup (struct zserv *client, u_short length) +zread_ipv4_nexthop_lookup (struct zserv *client, u_short length, + vrf_id_t vrf_id) { struct in_addr addr; + char buf[BUFSIZ]; addr.s_addr = stream_get_ipv4 (client->ibuf); - return zsend_ipv4_nexthop_lookup (client, addr); + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: looking up %s", __func__, + inet_ntop (AF_INET, &addr, buf, BUFSIZ)); + return zsend_ipv4_nexthop_lookup (client, addr, vrf_id); } +/* MRIB Nexthop lookup for IPv4. */ +static int +zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, + vrf_id_t vrf_id) +{ + struct in_addr addr; + struct rib *rib; + + addr.s_addr = stream_get_ipv4 (client->ibuf); + rib = rib_match_ipv4_multicast (addr, NULL, vrf_id); + return zsend_ipv4_nexthop_lookup_mrib (client, addr, rib); +} + /* Nexthop lookup for IPv4. */ static int -zread_ipv4_import_lookup (struct zserv *client, u_short length) +zread_ipv4_import_lookup (struct zserv *client, u_short length, + vrf_id_t vrf_id) { struct prefix_ipv4 p; @@ -905,13 +1030,13 @@ zread_ipv4_import_lookup (struct zserv *client, u_shor p.prefixlen = stream_getc (client->ibuf); p.prefix.s_addr = stream_get_ipv4 (client->ibuf); - return zsend_ipv4_import_lookup (client, &p); + return zsend_ipv4_import_lookup (client, &p, vrf_id); } #ifdef HAVE_IPV6 /* Zebra server IPv6 prefix add function. */ static int -zread_ipv6_add (struct zserv *client, u_short length) +zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id) { int i; struct stream *s; @@ -967,19 +1092,26 @@ zread_ipv6_add (struct zserv *client, u_short length) api.metric = stream_getl (s); else api.metric = 0; + + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_MTU)) + api.mtu = stream_getl (s); + else + api.mtu = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, zebrad.rtm_table_default, api.metric, - api.distance, api.safi); + rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, + vrf_id, zebrad.rtm_table_default, api.metric, + api.mtu, api.distance, api.safi); else - rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, zebrad.rtm_table_default, api.metric, - api.distance, api.safi); + rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, + vrf_id, zebrad.rtm_table_default, api.metric, + api.mtu, api.distance, api.safi); return 0; } /* Zebra server IPv6 prefix delete function. */ static int -zread_ipv6_delete (struct zserv *client, u_short length) +zread_ipv6_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) { int i; struct stream *s; @@ -1036,44 +1168,49 @@ zread_ipv6_delete (struct zserv *client, u_short lengt api.metric = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, vrf_id, + api.safi); else - rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, vrf_id, + api.safi); return 0; } static int -zread_ipv6_nexthop_lookup (struct zserv *client, u_short length) +zread_ipv6_nexthop_lookup (struct zserv *client, u_short length, + vrf_id_t vrf_id) { struct in6_addr addr; char buf[BUFSIZ]; stream_get (&addr, client->ibuf, 16); - printf ("DEBUG %s\n", inet_ntop (AF_INET6, &addr, buf, BUFSIZ)); + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: looking up %s", __func__, + inet_ntop (AF_INET6, &addr, buf, BUFSIZ)); - return zsend_ipv6_nexthop_lookup (client, &addr); + return zsend_ipv6_nexthop_lookup (client, &addr, vrf_id); } #endif /* HAVE_IPV6 */ /* Register zebra server router-id information. Send current router-id */ static int -zread_router_id_add (struct zserv *client, u_short length) +zread_router_id_add (struct zserv *client, u_short length, vrf_id_t vrf_id) { struct prefix p; /* Router-id information is needed. */ - client->ridinfo = 1; + vrf_bitmap_set (client->ridinfo, vrf_id); - router_id_get (&p); + router_id_get (&p, vrf_id); - return zsend_router_id_update (client,&p); + return zsend_router_id_update (client, &p, vrf_id); } /* Unregister zebra server router-id information. */ static int -zread_router_id_delete (struct zserv *client, u_short length) +zread_router_id_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) { - client->ridinfo = 0; + vrf_bitmap_unset (client->ridinfo, vrf_id); return 0; } @@ -1102,6 +1239,21 @@ zread_hello (struct zserv *client) } } +/* Unregister all information in a VRF. */ +static int +zread_vrf_unregister (struct zserv *client, u_short length, vrf_id_t vrf_id) +{ + int i; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + vrf_bitmap_unset (client->redist[i], vrf_id); + vrf_bitmap_unset (client->redist_default, vrf_id); + vrf_bitmap_unset (client->ifinfo, vrf_id); + vrf_bitmap_unset (client->ridinfo, vrf_id); + + return 0; +} + /* If client sent routes of specific type, zebra removes it * and returns number of deleted routes. */ @@ -1158,6 +1310,7 @@ static void zebra_client_create (int sock) { struct zserv *client; + int i; client = XCALLOC (0, sizeof (struct zserv)); @@ -1170,6 +1323,13 @@ zebra_client_create (int sock) /* Set table number. */ client->rtm_table = zebrad.rtm_table_default; + /* Initialize flags */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + client->redist[i] = vrf_bitmap_init (); + client->redist_default = vrf_bitmap_init (); + client->ifinfo = vrf_bitmap_init (); + client->ridinfo = vrf_bitmap_init (); + /* Add this client to linked list. */ listnode_add (zebrad.client_list, client); @@ -1186,6 +1346,7 @@ zebra_client_read (struct thread *thread) size_t already; uint16_t length, command; uint8_t marker, version; + vrf_id_t vrf_id; /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD (thread); @@ -1227,6 +1388,7 @@ zebra_client_read (struct thread *thread) length = stream_getw (client->ibuf); marker = stream_getc (client->ibuf); version = stream_getc (client->ibuf); + vrf_id = stream_getw (client->ibuf); command = stream_getw (client->ibuf); if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) @@ -1279,63 +1441,69 @@ zebra_client_read (struct thread *thread) zlog_debug ("zebra message comes from socket [%d]", sock); if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug ("zebra message received [%s] %d", - zserv_command_string (command), length); + zlog_debug ("zebra message received [%s] %d in VRF %u", + zserv_command_string (command), length, vrf_id); switch (command) { case ZEBRA_ROUTER_ID_ADD: - zread_router_id_add (client, length); + zread_router_id_add (client, length, vrf_id); break; case ZEBRA_ROUTER_ID_DELETE: - zread_router_id_delete (client, length); + zread_router_id_delete (client, length, vrf_id); break; case ZEBRA_INTERFACE_ADD: - zread_interface_add (client, length); + zread_interface_add (client, length, vrf_id); break; case ZEBRA_INTERFACE_DELETE: - zread_interface_delete (client, length); + zread_interface_delete (client, length, vrf_id); break; case ZEBRA_IPV4_ROUTE_ADD: - zread_ipv4_add (client, length); + zread_ipv4_add (client, length, vrf_id); break; case ZEBRA_IPV4_ROUTE_DELETE: - zread_ipv4_delete (client, length); + zread_ipv4_delete (client, length, vrf_id); break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_ROUTE_ADD: - zread_ipv6_add (client, length); + zread_ipv6_add (client, length, vrf_id); break; case ZEBRA_IPV6_ROUTE_DELETE: - zread_ipv6_delete (client, length); + zread_ipv6_delete (client, length, vrf_id); break; #endif /* HAVE_IPV6 */ case ZEBRA_REDISTRIBUTE_ADD: - zebra_redistribute_add (command, client, length); + zebra_redistribute_add (command, client, length, vrf_id); break; case ZEBRA_REDISTRIBUTE_DELETE: - zebra_redistribute_delete (command, client, length); + zebra_redistribute_delete (command, client, length, vrf_id); break; case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: - zebra_redistribute_default_add (command, client, length); + zebra_redistribute_default_add (command, client, length, vrf_id); break; case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: - zebra_redistribute_default_delete (command, client, length); + zebra_redistribute_default_delete (command, client, length, vrf_id); break; case ZEBRA_IPV4_NEXTHOP_LOOKUP: - zread_ipv4_nexthop_lookup (client, length); + zread_ipv4_nexthop_lookup (client, length, vrf_id); break; + case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: + zread_ipv4_nexthop_lookup_mrib (client, length, vrf_id); + break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_NEXTHOP_LOOKUP: - zread_ipv6_nexthop_lookup (client, length); + zread_ipv6_nexthop_lookup (client, length, vrf_id); break; #endif /* HAVE_IPV6 */ case ZEBRA_IPV4_IMPORT_LOOKUP: - zread_ipv4_import_lookup (client, length); + zread_ipv4_import_lookup (client, length, vrf_id); break; case ZEBRA_HELLO: zread_hello (client); break; + case ZEBRA_VRF_UNREGISTER: + zread_vrf_unregister (client, length, vrf_id); + break; default: zlog_info ("Zebra received unknown command %d", command); break; @@ -1446,7 +1614,7 @@ zebra_serv () zebra_event (ZEBRA_SERV, accept_sock, NULL); } -#endif /* HAVE_TCP_ZEBRA */ +#else /* HAVE_TCP_ZEBRA */ /* For sockaddr_un. */ #include @@ -1512,8 +1680,9 @@ zebra_serv_un (const char *path) zebra_event (ZEBRA_SERV, sock, NULL); } - +#endif /* HAVE_TCP_ZEBRA */ + static void zebra_event (enum event event, int sock, struct zserv *client) { @@ -1531,7 +1700,7 @@ zebra_event (enum event event, int sock, struct zserv break; } } - + /* Display default rtm_table for all clients. */ DEFUN (show_table, show_table_cmd, @@ -1631,7 +1800,7 @@ static struct cmd_node table_node = "", /* This node has no interface. */ 1 }; - + /* Only display ip forwarding is enabled or not. */ DEFUN (show_ip_forwarding, show_ip_forwarding_cmd, @@ -1752,7 +1921,7 @@ static struct cmd_node forwarding_node = 1 }; - + /* Initialisation of zebra and installation of commands. */ void zebra_init (void)