forked from Mirror/frr
zebra: ZEBRA_HELLO and mopping up routes (BZ#448)
ZEBRA_HELLO message is used by routing daemons to inform zebra what type of routes daemon will be announcing to zebra. Also zebra uses route_type_oaths array to track which daemon announces which protocol. Zebra mops up routes if daemon didn't for some reason.
This commit is contained in:
parent
2654e43ca2
commit
2ea1ab1c30
|
@ -318,6 +318,25 @@ zebra_message_send (struct zclient *zclient, int command)
|
||||||
return zclient_send_message(zclient);
|
return zclient_send_message(zclient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zebra_hello_send (struct zclient *zclient)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
|
||||||
|
if (zclient->redist_default)
|
||||||
|
{
|
||||||
|
s = zclient->obuf;
|
||||||
|
stream_reset (s);
|
||||||
|
|
||||||
|
zclient_create_header (s, ZEBRA_HELLO);
|
||||||
|
stream_putc (s, zclient->redist_default);
|
||||||
|
stream_putw_at (s, 0, stream_get_endp (s));
|
||||||
|
return zclient_send_message(zclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make connection to zebra daemon. */
|
/* Make connection to zebra daemon. */
|
||||||
int
|
int
|
||||||
zclient_start (struct zclient *zclient)
|
zclient_start (struct zclient *zclient)
|
||||||
|
@ -359,6 +378,8 @@ zclient_start (struct zclient *zclient)
|
||||||
/* Create read thread. */
|
/* Create read thread. */
|
||||||
zclient_event (ZCLIENT_READ, zclient);
|
zclient_event (ZCLIENT_READ, zclient);
|
||||||
|
|
||||||
|
zebra_hello_send (zclient);
|
||||||
|
|
||||||
/* We need router-id information. */
|
/* We need router-id information. */
|
||||||
zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD);
|
zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD);
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,8 @@ struct in_pktinfo
|
||||||
#define ZEBRA_ROUTER_ID_ADD 20
|
#define ZEBRA_ROUTER_ID_ADD 20
|
||||||
#define ZEBRA_ROUTER_ID_DELETE 21
|
#define ZEBRA_ROUTER_ID_DELETE 21
|
||||||
#define ZEBRA_ROUTER_ID_UPDATE 22
|
#define ZEBRA_ROUTER_ID_UPDATE 22
|
||||||
#define ZEBRA_MESSAGE_MAX 23
|
#define ZEBRA_HELLO 23
|
||||||
|
#define ZEBRA_MESSAGE_MAX 24
|
||||||
|
|
||||||
/* Marker value used in new Zserv, in the byte location corresponding
|
/* Marker value used in new Zserv, in the byte location corresponding
|
||||||
* the command value in the old zserv header. To allow old and new
|
* the command value in the old zserv header. To allow old and new
|
||||||
|
|
|
@ -266,6 +266,7 @@ extern void rib_weed_tables (void);
|
||||||
extern void rib_sweep_route (void);
|
extern void rib_sweep_route (void);
|
||||||
extern void rib_close (void);
|
extern void rib_close (void);
|
||||||
extern void rib_init (void);
|
extern void rib_init (void);
|
||||||
|
extern unsigned long rib_score_proto (u_char proto);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
|
static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
|
||||||
|
|
|
@ -2881,7 +2881,41 @@ rib_sweep_route (void)
|
||||||
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
|
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
|
||||||
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
|
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove specific by protocol routes from 'table'. */
|
||||||
|
static unsigned long
|
||||||
|
rib_score_proto_table (u_char proto, struct route_table *table)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
struct rib *rib;
|
||||||
|
struct rib *next;
|
||||||
|
unsigned long n = 0;
|
||||||
|
|
||||||
|
if (table)
|
||||||
|
for (rn = route_top (table); rn; rn = route_next (rn))
|
||||||
|
for (rib = rn->info; rib; rib = next)
|
||||||
|
{
|
||||||
|
next = rib->next;
|
||||||
|
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
||||||
|
continue;
|
||||||
|
if (rib->type == proto)
|
||||||
|
{
|
||||||
|
rib_delnode (rn, rib);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove specific by protocol routes. */
|
||||||
|
unsigned long
|
||||||
|
rib_score_proto (u_char proto)
|
||||||
|
{
|
||||||
|
return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
|
||||||
|
+rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/* Close RIB and clean up kernel routes. */
|
/* Close RIB and clean up kernel routes. */
|
||||||
static void
|
static void
|
||||||
rib_close_table (struct route_table *table)
|
rib_close_table (struct route_table *table)
|
||||||
|
|
|
@ -64,6 +64,15 @@ zserv_delayed_close(struct thread *thread)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When client connects, it sends hello message
|
||||||
|
* with promise to send zebra routes of specific type.
|
||||||
|
* Zebra stores a socket fd of the client into
|
||||||
|
* this array. And use it to clean up routes that
|
||||||
|
* client didn't remove for some reasons after closing
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
static int route_type_oaths[ZEBRA_ROUTE_MAX];
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zserv_flush_data(struct thread *thread)
|
zserv_flush_data(struct thread *thread)
|
||||||
{
|
{
|
||||||
|
@ -1071,6 +1080,49 @@ zread_router_id_delete (struct zserv *client, u_short length)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tie up route-type and client->sock */
|
||||||
|
static void
|
||||||
|
zread_hello (struct zserv *client)
|
||||||
|
{
|
||||||
|
/* type of protocol (lib/zebra.h) */
|
||||||
|
u_char proto;
|
||||||
|
proto = stream_getc (client->ibuf);
|
||||||
|
|
||||||
|
/* accept only dynamic routing protocols */
|
||||||
|
if ((proto < ZEBRA_ROUTE_MAX)
|
||||||
|
&& (proto > ZEBRA_ROUTE_STATIC))
|
||||||
|
{
|
||||||
|
zlog_notice ("client %d says hello and bids fair to announce only %s routes",
|
||||||
|
client->sock, zebra_route_string(proto));
|
||||||
|
|
||||||
|
/* if route-type was binded by other client */
|
||||||
|
if (route_type_oaths[proto])
|
||||||
|
zlog_warn ("sender of %s routes changed %c->%c",
|
||||||
|
zebra_route_string(proto), route_type_oaths[proto],
|
||||||
|
client->sock);
|
||||||
|
|
||||||
|
route_type_oaths[proto] = client->sock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If client sent routes of specific type, zebra removes it
|
||||||
|
* and returns number of deleted routes.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zebra_score_rib (int client_sock)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++)
|
||||||
|
if (client_sock == route_type_oaths[i])
|
||||||
|
{
|
||||||
|
zlog_notice ("client %d disconnected. %lu %s routes removed from the rib",
|
||||||
|
client_sock, rib_score_proto (i), zebra_route_string (i));
|
||||||
|
route_type_oaths[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Close zebra client. */
|
/* Close zebra client. */
|
||||||
static void
|
static void
|
||||||
zebra_client_close (struct zserv *client)
|
zebra_client_close (struct zserv *client)
|
||||||
|
@ -1079,6 +1131,7 @@ zebra_client_close (struct zserv *client)
|
||||||
if (client->sock)
|
if (client->sock)
|
||||||
{
|
{
|
||||||
close (client->sock);
|
close (client->sock);
|
||||||
|
zebra_score_rib (client->sock);
|
||||||
client->sock = -1;
|
client->sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,6 +1336,9 @@ zebra_client_read (struct thread *thread)
|
||||||
case ZEBRA_IPV4_IMPORT_LOOKUP:
|
case ZEBRA_IPV4_IMPORT_LOOKUP:
|
||||||
zread_ipv4_import_lookup (client, length);
|
zread_ipv4_import_lookup (client, length);
|
||||||
break;
|
break;
|
||||||
|
case ZEBRA_HELLO:
|
||||||
|
zread_hello (client);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
zlog_info ("Zebra received unknown command %d", command);
|
zlog_info ("Zebra received unknown command %d", command);
|
||||||
break;
|
break;
|
||||||
|
@ -1352,6 +1408,7 @@ zebra_serv ()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset (&route_type_oaths, 0, sizeof (route_type_oaths));
|
||||||
memset (&addr, 0, sizeof (struct sockaddr_in));
|
memset (&addr, 0, sizeof (struct sockaddr_in));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons (ZEBRA_PORT);
|
addr.sin_port = htons (ZEBRA_PORT);
|
||||||
|
@ -1422,6 +1479,8 @@ zebra_serv_un (const char *path)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset (&route_type_oaths, 0, sizeof (route_type_oaths));
|
||||||
|
|
||||||
/* Make server socket. */
|
/* Make server socket. */
|
||||||
memset (&serv, 0, sizeof (struct sockaddr_un));
|
memset (&serv, 0, sizeof (struct sockaddr_un));
|
||||||
serv.sun_family = AF_UNIX;
|
serv.sun_family = AF_UNIX;
|
||||||
|
|
Loading…
Reference in a new issue