2002-12-13 21:15:29 +01:00
|
|
|
/* Zebra daemon server header.
|
|
|
|
* Copyright (C) 1997, 98 Kunihiro Ishiguro
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
|
|
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _ZEBRA_ZSERV_H
|
|
|
|
#define _ZEBRA_ZSERV_H
|
|
|
|
|
2004-07-23 17:26:14 +02:00
|
|
|
#include "rib.h"
|
2005-11-24 16:15:17 +01:00
|
|
|
#include "if.h"
|
2005-04-28 Paul Jakma <paul.jakma@sun.com>
* rib.h: (struct rib) Add lock field for refcounting.
* zserv.h: (struct zebra_t) Add a ribq workqueue to the zebra
'master' struct.
* zserv.c: (zread_ipv4_add) XMALLOC then memset should be XCALLOC.
* zebra_rib.c: Clean up refcounting of route_node, make struct rib
refcounted and convert rib_process to work-queue. In general,
rib's should be rib_addnode'd and delnode'd to route_nodes, and
these symmetrical functions will manage the locking of referenced
route_node and freeing of struct rib - rather than having users
manage each seperately - with much scope for bugs..
(newrib_free) removed and replaced with rib_lock
(rib_lock) new function, check state of lock and increment.
(rib_unlock) new function, check lock state and decrement. Free
struct rib if refcount hits 0, freeing struct nexthop's, as
newrib_free did.
(rib_addnode) Add RIB to route_node, locking both.
(rib_delnode) Delete RIB from route_node, unlocking each.
(rib_process) Converted to a work-queue work function.
Functional changes are minimal, just arguments, comments and
whitespace.
(rib_queue_add_qnode) Helper function to setup a ribq item.
(rib_queue_add) Helper function, same arguments as old
rib_process, to replace in callers of rib_process.
(rib_queue_qnode_del) ribq deconstructor.
(rib_queue_init) Create the ribq.
(rib_init) call rib_queue_init.
(remainder) Sanitise refcounting of route_node's. Convert to
rib_queue_add, rib_addnode and rib_delnode. Change XMALLOC/memset
to XCALLOC. Remove calls to nexthop_delete and nexthop_free.
2005-04-28 19:35:14 +02:00
|
|
|
#include "workqueue.h"
|
2015-05-20 02:40:45 +02:00
|
|
|
#include "routemap.h"
|
2015-05-20 03:04:26 +02:00
|
|
|
#include "vty.h"
|
Multi-Instance OSPF Summary
——————————————-------------
- etc/init.d/quagga is modified to support creating separate ospf daemon
process for each instance. Each individual instance is monitored by
watchquagga just like any protocol daemons.(requires initd-mi.patch).
- Vtysh is modified to able to connect to multiple daemons of the same
protocol (supported for OSPF only for now).
- ospfd is modified to remember the Instance-ID that its invoked with. For
the entire life of the process it caters to any command request that
matches that instance-ID (unless its a non instance specific command).
Routes/messages to zebra are tagged with instance-ID.
- zebra route/redistribute mechanisms are modified to work with
[protocol type + instance-id]
- bgpd now has ability to have multiple instance specific redistribution
for a protocol (OSPF only supported/tested for now).
- zlog ability to display instance-id besides the protocol/daemon name.
- Changes in other daemons are to because of the needed integration with
some of the modified APIs/routines. (Didn’t prefer replicating too many
separate instance specific APIs.)
- config/show/debug commands are modified to take instance-id argument
as appropriate.
Guidelines to start using multi-instance ospf
---------------------------------------------
The patch is backward compatible, i.e for any previous way of single ospf
deamon(router ospf <cr>) will continue to work as is, including all the
show commands etc.
To enable multiple instances, do the following:
1. service quagga stop
2. Modify /etc/quagga/daemons to add instance-ids of each desired
instance in the following format:
ospfd=“yes"
ospfd_instances="1,2,3"
assuming you want to enable 3 instances with those instance ids.
3. Create corresponding ospfd config files as ospfd-1.conf, ospfd-2.conf
and ospfd-3.conf.
4. service quagga start/restart
5. Verify that the deamons are started as expected. You should see
ospfd started with -n <instance-id> option.
ps –ef | grep quagga
With that /var/run/quagga/ should have ospfd-<instance-id>.pid and
ospfd-<instance-id>/vty to each instance.
6. vtysh to work with instances as you would with any other deamons.
7. Overall most quagga semantics are the same working with the instance
deamon, like it is for any other daemon.
NOTE:
To safeguard against errors leading to too many processes getting invoked,
a hard limit on number of instance-ids is in place, currently its 5.
Allowed instance-id range is <1-65535>
Once daemons are up, show running from vtysh should show the instance-id
of each daemon as 'router ospf <instance-id>’ (without needing explicit
configuration)
Instance-id can not be changed via vtysh, other router ospf configuration
is allowed as before.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
2015-05-20 03:03:42 +02:00
|
|
|
#include "zclient.h"
|
2004-07-23 17:26:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Default port information. */
|
|
|
|
#define ZEBRA_VTY_PORT 2601
|
|
|
|
|
|
|
|
/* Default configuration filename. */
|
|
|
|
#define DEFAULT_CONFIG_FILE "zebra.conf"
|
|
|
|
|
2015-05-20 02:40:45 +02:00
|
|
|
#define ZEBRA_RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Client structure. */
|
|
|
|
struct zserv
|
|
|
|
{
|
|
|
|
/* Client file descriptor. */
|
|
|
|
int sock;
|
|
|
|
|
|
|
|
/* Input/output buffer to the client. */
|
|
|
|
struct stream *ibuf;
|
|
|
|
struct stream *obuf;
|
|
|
|
|
2005-02-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* zserv.c: Must include network.h and buffer.h for non-blocking I/O.
Remove global message_queue and t_write (need separate buffering for
each client).
(zebra_server_dequeue,zebra_server_enqueue) Remove functions
related to old buggy buffering code.
(zserv_delayed_close) New thread callback function to delete a client.
(zserv_flush_data) New thread callback function to flush buffered
data to client.
(zebra_server_send_message) Rewritten to use buffer_write (so
buffering of writes and non-blocking I/O work properly).
(zsend_interface_add,zsend_interface_delete,zsend_interface_address,
zsend_interface_update) Return 0 instead of -1 if !client->ifinfo
(this is not really an error). Return value from
zebra_server_send_message.
(zsend_route_multipath,zsend_ipv4_nexthop_lookup,
zsend_ipv4_import_lookup) Return value from zebra_server_send_message.
(zsend_ipv6_nexthop_lookup) Fix scope to static, and return value
from zebra_server_send_message.
(zsend_router_id_update) Must use zebra_server_send_message instead
of deprecated writen function. Return 0 instead of -1 if this client
is not subscribed to router-id updates (since this is not really
an error).
(zread_interface_add) Change type to static int. If
zsend_interface_add fails or zsend_interface_address fails, return -1
immediately (since the client has had an I/O error).
(zread_interface_delete,zread_ipv4_add,zread_ipv4_delete,
zread_ipv6_add,zread_ipv6_delete,zread_router_id_delete) Return 0
to indicate success.
(zread_ipv4_nexthop_lookup) Return value from
zsend_ipv4_nexthop_lookup.
(zread_ipv4_import_lookup) Return value from zsend_ipv4_import_lookup.
(zebra_read_ipv6) Remove unused function.
(zread_ipv6_nexthop_lookup) Return value from
zsend_ipv6_nexthop_lookup.
(zread_router_id_add) Return value from zsend_router_id_update.
(zebra_client_close) Call buffer_free(client->wb) and
thread_cancel(client->t_suicide).
(zebra_client_create) Allocate client->wb using buffer_new.
(zebra_client_read) Support non-blocking I/O by using stream_read_try.
Use ZEBRA_HEADER_SIZE instead of 3.
(zebra_accept) Fix bug: reset accept thread at top. Make client
socket non-blocking using the set_nonblocking function.
(config_write_forwarding) Fix scope to static.
(zebra_init) Remove initialization code for old buggy write buffering.
* zserv.h: Add 2 new fields to struct zserv: struct buffer *wb
(to enable buffered writes with non-blocking I/), and
struct thread *t_suicide to support delayed close on I/O
errors.
* router-id.h: Remove prototypes for zread_router_id_add and
zread_router_id_delete (their scope should be static to zserv.c).
2005-02-28 21:52:15 +01:00
|
|
|
/* Buffer of data waiting to be written to client. */
|
|
|
|
struct buffer *wb;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Threads for read/write. */
|
|
|
|
struct thread *t_read;
|
|
|
|
struct thread *t_write;
|
|
|
|
|
2005-02-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* zserv.c: Must include network.h and buffer.h for non-blocking I/O.
Remove global message_queue and t_write (need separate buffering for
each client).
(zebra_server_dequeue,zebra_server_enqueue) Remove functions
related to old buggy buffering code.
(zserv_delayed_close) New thread callback function to delete a client.
(zserv_flush_data) New thread callback function to flush buffered
data to client.
(zebra_server_send_message) Rewritten to use buffer_write (so
buffering of writes and non-blocking I/O work properly).
(zsend_interface_add,zsend_interface_delete,zsend_interface_address,
zsend_interface_update) Return 0 instead of -1 if !client->ifinfo
(this is not really an error). Return value from
zebra_server_send_message.
(zsend_route_multipath,zsend_ipv4_nexthop_lookup,
zsend_ipv4_import_lookup) Return value from zebra_server_send_message.
(zsend_ipv6_nexthop_lookup) Fix scope to static, and return value
from zebra_server_send_message.
(zsend_router_id_update) Must use zebra_server_send_message instead
of deprecated writen function. Return 0 instead of -1 if this client
is not subscribed to router-id updates (since this is not really
an error).
(zread_interface_add) Change type to static int. If
zsend_interface_add fails or zsend_interface_address fails, return -1
immediately (since the client has had an I/O error).
(zread_interface_delete,zread_ipv4_add,zread_ipv4_delete,
zread_ipv6_add,zread_ipv6_delete,zread_router_id_delete) Return 0
to indicate success.
(zread_ipv4_nexthop_lookup) Return value from
zsend_ipv4_nexthop_lookup.
(zread_ipv4_import_lookup) Return value from zsend_ipv4_import_lookup.
(zebra_read_ipv6) Remove unused function.
(zread_ipv6_nexthop_lookup) Return value from
zsend_ipv6_nexthop_lookup.
(zread_router_id_add) Return value from zsend_router_id_update.
(zebra_client_close) Call buffer_free(client->wb) and
thread_cancel(client->t_suicide).
(zebra_client_create) Allocate client->wb using buffer_new.
(zebra_client_read) Support non-blocking I/O by using stream_read_try.
Use ZEBRA_HEADER_SIZE instead of 3.
(zebra_accept) Fix bug: reset accept thread at top. Make client
socket non-blocking using the set_nonblocking function.
(config_write_forwarding) Fix scope to static.
(zebra_init) Remove initialization code for old buggy write buffering.
* zserv.h: Add 2 new fields to struct zserv: struct buffer *wb
(to enable buffered writes with non-blocking I/), and
struct thread *t_suicide to support delayed close on I/O
errors.
* router-id.h: Remove prototypes for zread_router_id_add and
zread_router_id_delete (their scope should be static to zserv.c).
2005-02-28 21:52:15 +01:00
|
|
|
/* Thread for delayed close. */
|
|
|
|
struct thread *t_suicide;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* default routing table this client munges */
|
|
|
|
int rtm_table;
|
|
|
|
|
|
|
|
/* This client's redistribute flag. */
|
2015-05-20 03:03:45 +02:00
|
|
|
struct redist_proto redist[AFI_MAX][ZEBRA_ROUTE_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Redistribute default route flag. */
|
|
|
|
u_char redist_default;
|
|
|
|
|
|
|
|
/* Interface information. */
|
|
|
|
u_char ifinfo;
|
2004-10-03 20:18:34 +02:00
|
|
|
|
|
|
|
/* Router-id information. */
|
|
|
|
u_char ridinfo;
|
2015-05-20 02:40:34 +02:00
|
|
|
|
|
|
|
/* client's protocol */
|
|
|
|
u_char proto;
|
Multi-Instance OSPF Summary
——————————————-------------
- etc/init.d/quagga is modified to support creating separate ospf daemon
process for each instance. Each individual instance is monitored by
watchquagga just like any protocol daemons.(requires initd-mi.patch).
- Vtysh is modified to able to connect to multiple daemons of the same
protocol (supported for OSPF only for now).
- ospfd is modified to remember the Instance-ID that its invoked with. For
the entire life of the process it caters to any command request that
matches that instance-ID (unless its a non instance specific command).
Routes/messages to zebra are tagged with instance-ID.
- zebra route/redistribute mechanisms are modified to work with
[protocol type + instance-id]
- bgpd now has ability to have multiple instance specific redistribution
for a protocol (OSPF only supported/tested for now).
- zlog ability to display instance-id besides the protocol/daemon name.
- Changes in other daemons are to because of the needed integration with
some of the modified APIs/routines. (Didn’t prefer replicating too many
separate instance specific APIs.)
- config/show/debug commands are modified to take instance-id argument
as appropriate.
Guidelines to start using multi-instance ospf
---------------------------------------------
The patch is backward compatible, i.e for any previous way of single ospf
deamon(router ospf <cr>) will continue to work as is, including all the
show commands etc.
To enable multiple instances, do the following:
1. service quagga stop
2. Modify /etc/quagga/daemons to add instance-ids of each desired
instance in the following format:
ospfd=“yes"
ospfd_instances="1,2,3"
assuming you want to enable 3 instances with those instance ids.
3. Create corresponding ospfd config files as ospfd-1.conf, ospfd-2.conf
and ospfd-3.conf.
4. service quagga start/restart
5. Verify that the deamons are started as expected. You should see
ospfd started with -n <instance-id> option.
ps –ef | grep quagga
With that /var/run/quagga/ should have ospfd-<instance-id>.pid and
ospfd-<instance-id>/vty to each instance.
6. vtysh to work with instances as you would with any other deamons.
7. Overall most quagga semantics are the same working with the instance
deamon, like it is for any other daemon.
NOTE:
To safeguard against errors leading to too many processes getting invoked,
a hard limit on number of instance-ids is in place, currently its 5.
Allowed instance-id range is <1-65535>
Once daemons are up, show running from vtysh should show the instance-id
of each daemon as 'router ospf <instance-id>’ (without needing explicit
configuration)
Instance-id can not be changed via vtysh, other router ospf configuration
is allowed as before.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
2015-05-20 03:03:42 +02:00
|
|
|
u_short instance;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
|
|
|
/* Statistics */
|
|
|
|
u_int32_t redist_v4_add_cnt;
|
|
|
|
u_int32_t redist_v4_del_cnt;
|
|
|
|
u_int32_t redist_v6_add_cnt;
|
|
|
|
u_int32_t redist_v6_del_cnt;
|
|
|
|
u_int32_t v4_route_add_cnt;
|
|
|
|
u_int32_t v4_route_upd8_cnt;
|
|
|
|
u_int32_t v4_route_del_cnt;
|
|
|
|
u_int32_t v6_route_add_cnt;
|
|
|
|
u_int32_t v6_route_del_cnt;
|
|
|
|
u_int32_t v6_route_upd8_cnt;
|
|
|
|
u_int32_t connected_rt_add_cnt;
|
|
|
|
u_int32_t connected_rt_del_cnt;
|
|
|
|
u_int32_t ifup_cnt;
|
|
|
|
u_int32_t ifdown_cnt;
|
|
|
|
u_int32_t ifadd_cnt;
|
|
|
|
u_int32_t ifdel_cnt;
|
2015-05-20 02:47:23 +02:00
|
|
|
u_int32_t if_bfd_cnt;
|
2015-06-12 16:59:11 +02:00
|
|
|
u_int32_t bfd_peer_add_cnt;
|
|
|
|
u_int32_t bfd_peer_upd8_cnt;
|
|
|
|
u_int32_t bfd_peer_del_cnt;
|
|
|
|
u_int32_t bfd_peer_replay_cnt;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
|
|
|
time_t connect_time;
|
|
|
|
time_t last_read_time;
|
|
|
|
time_t last_write_time;
|
|
|
|
time_t nh_reg_time;
|
|
|
|
time_t nh_dereg_time;
|
|
|
|
time_t nh_last_upd_time;
|
|
|
|
|
|
|
|
int last_read_cmd;
|
|
|
|
int last_write_cmd;
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
2003-06-15 03:28:29 +02:00
|
|
|
/* Zebra instance */
|
|
|
|
struct zebra_t
|
|
|
|
{
|
|
|
|
/* Thread master */
|
|
|
|
struct thread_master *master;
|
2004-09-23 21:18:23 +02:00
|
|
|
struct list *client_list;
|
2003-06-15 03:28:29 +02:00
|
|
|
|
|
|
|
/* default table */
|
2015-05-20 03:04:26 +02:00
|
|
|
u_int32_t rtm_table_default;
|
2005-04-28 Paul Jakma <paul.jakma@sun.com>
* rib.h: (struct rib) Add lock field for refcounting.
* zserv.h: (struct zebra_t) Add a ribq workqueue to the zebra
'master' struct.
* zserv.c: (zread_ipv4_add) XMALLOC then memset should be XCALLOC.
* zebra_rib.c: Clean up refcounting of route_node, make struct rib
refcounted and convert rib_process to work-queue. In general,
rib's should be rib_addnode'd and delnode'd to route_nodes, and
these symmetrical functions will manage the locking of referenced
route_node and freeing of struct rib - rather than having users
manage each seperately - with much scope for bugs..
(newrib_free) removed and replaced with rib_lock
(rib_lock) new function, check state of lock and increment.
(rib_unlock) new function, check lock state and decrement. Free
struct rib if refcount hits 0, freeing struct nexthop's, as
newrib_free did.
(rib_addnode) Add RIB to route_node, locking both.
(rib_delnode) Delete RIB from route_node, unlocking each.
(rib_process) Converted to a work-queue work function.
Functional changes are minimal, just arguments, comments and
whitespace.
(rib_queue_add_qnode) Helper function to setup a ribq item.
(rib_queue_add) Helper function, same arguments as old
rib_process, to replace in callers of rib_process.
(rib_queue_qnode_del) ribq deconstructor.
(rib_queue_init) Create the ribq.
(rib_init) call rib_queue_init.
(remainder) Sanitise refcounting of route_node's. Convert to
rib_queue_add, rib_addnode and rib_delnode. Change XMALLOC/memset
to XCALLOC. Remove calls to nexthop_delete and nexthop_free.
2005-04-28 19:35:14 +02:00
|
|
|
|
|
|
|
/* rib work queue */
|
|
|
|
struct work_queue *ribq;
|
2008-06-02 14:03:22 +02:00
|
|
|
struct meta_queue *mq;
|
2003-06-15 03:28:29 +02:00
|
|
|
};
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Count prefix size from mask length */
|
|
|
|
#define PSIZE(a) (((a) + 7) / (8))
|
|
|
|
|
|
|
|
/* Prototypes. */
|
2005-06-28 19:17:12 +02:00
|
|
|
extern void zebra_init (void);
|
|
|
|
extern void zebra_if_init (void);
|
2011-11-25 15:51:48 +01:00
|
|
|
extern void zebra_zserv_socket_init (char *path);
|
2005-06-28 19:17:12 +02:00
|
|
|
extern void hostinfo_get (void);
|
|
|
|
extern void rib_init (void);
|
2014-07-03 12:23:09 +02:00
|
|
|
extern void interface_list (struct zebra_vrf *);
|
|
|
|
extern void route_read (struct zebra_vrf *);
|
|
|
|
extern void kernel_init (struct zebra_vrf *);
|
|
|
|
extern void kernel_terminate (struct zebra_vrf *);
|
2007-05-02 18:05:35 +02:00
|
|
|
extern void zebra_route_map_init (void);
|
2005-06-28 19:17:12 +02:00
|
|
|
extern void zebra_snmp_init (void);
|
|
|
|
extern void zebra_vty_init (void);
|
|
|
|
|
|
|
|
extern int zsend_interface_add (struct zserv *, struct interface *);
|
|
|
|
extern int zsend_interface_delete (struct zserv *, struct interface *);
|
|
|
|
extern int zsend_interface_address (int, struct zserv *, struct interface *,
|
|
|
|
struct connected *);
|
2015-05-20 02:40:40 +02:00
|
|
|
extern void nbr_connected_replacement_add_ipv6 (struct interface *,
|
|
|
|
struct in6_addr *, u_char);
|
|
|
|
extern void nbr_connected_delete_ipv6 (struct interface *, struct in6_addr *, u_char);
|
2005-06-28 19:17:12 +02:00
|
|
|
extern int zsend_interface_update (int, struct zserv *, struct interface *);
|
2015-10-21 06:38:38 +02:00
|
|
|
extern int zsend_redistribute_route (int, struct zserv *, struct prefix *,
|
|
|
|
struct rib *);
|
2015-05-22 11:40:07 +02:00
|
|
|
extern int zsend_router_id_update (struct zserv *, struct prefix *,
|
|
|
|
vrf_id_t);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
extern pid_t pid;
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
extern void zserv_create_header(struct stream *s, uint16_t cmd);
|
2015-09-16 14:30:23 +02:00
|
|
|
extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const u_char);
|
2015-05-20 02:40:34 +02:00
|
|
|
extern int zebra_server_send_message(struct zserv *client);
|
|
|
|
|
2015-05-20 02:40:45 +02:00
|
|
|
extern void zebra_route_map_write_delay_timer(struct vty *);
|
|
|
|
extern route_map_result_t zebra_route_map_check (int family, int rib_type,
|
|
|
|
struct prefix *p,
|
2015-05-20 03:03:44 +02:00
|
|
|
struct nexthop *nexthop,
|
2015-05-22 11:40:04 +02:00
|
|
|
vrf_id_t vrf_id,
|
2015-05-20 03:03:44 +02:00
|
|
|
u_short tag);
|
2015-05-20 02:47:20 +02:00
|
|
|
extern route_map_result_t zebra_nht_route_map_check (int family,
|
|
|
|
int client_proto,
|
|
|
|
struct prefix *p,
|
|
|
|
struct rib *,
|
|
|
|
struct nexthop *nexthop);
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* _ZEBRA_ZEBRA_H */
|