2002-12-13 21:15:29 +01:00
|
|
|
/* Zebra daemon server routine.
|
|
|
|
* Copyright (C) 1997, 98, 99 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.
|
|
|
|
*
|
2017-05-13 10:25:29 +02:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2002-12-13 21:15:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
2017-08-06 07:35:50 +02:00
|
|
|
#include <sys/un.h>
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "memory.h"
|
2015-05-29 05:48:31 +02:00
|
|
|
#include "zebra_memory.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "table.h"
|
|
|
|
#include "rib.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "sockunion.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "zclient.h"
|
2003-06-04 15:59:38 +02:00
|
|
|
#include "privs.h"
|
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
|
|
|
#include "network.h"
|
|
|
|
#include "buffer.h"
|
2015-05-20 02:40:34 +02:00
|
|
|
#include "nexthop.h"
|
2015-05-22 11:40:02 +02:00
|
|
|
#include "vrf.h"
|
2017-08-06 07:35:50 +02:00
|
|
|
#include "libfrr.h"
|
2017-10-11 15:16:46 +02:00
|
|
|
#include "sockopt.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "zebra/zserv.h"
|
2016-04-14 15:20:47 +02:00
|
|
|
#include "zebra/zebra_ns.h"
|
|
|
|
#include "zebra/zebra_vrf.h"
|
2004-10-03 20:18:34 +02:00
|
|
|
#include "zebra/router-id.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "zebra/redistribute.h"
|
|
|
|
#include "zebra/debug.h"
|
|
|
|
#include "zebra/ipforward.h"
|
2015-05-20 02:40:34 +02:00
|
|
|
#include "zebra/zebra_rnh.h"
|
2015-06-11 18:19:59 +02:00
|
|
|
#include "zebra/rt_netlink.h"
|
2015-07-26 00:55:47 +02:00
|
|
|
#include "zebra/interface.h"
|
|
|
|
#include "zebra/zebra_ptm.h"
|
BGP: Trigger IPv6 router advertisements upon config of unnumbered neighbor
Instead of turning on IPv6 RA on every interface as soon as it has an IPv6
address, only enable it upon configuration of BGP neighbor. When the BGP
neighbor is deleted, signal that RAs can be turned off.
To support this, introduce new message interaction between BGP and Zebra.
Also, take appropriate actions in BGP upon interface add/del since the
unnumbered neighbor could exist prior to interface creation etc.
Only unnumbered IPv6 neighbors require RA, the /30 or /31 based neighbors
don't. However, to keep the interaction simple and not have to deal with
too many dynamic conditions (e.g., address deletes or neighbor change to/from
'v6only'), RAs on the interface are triggered upon any unnumbered neighbor
configuration.
BGP-triggered RAs will cause RAs to be initiated on the interface; however,
if BGP asks that RAs be stopped (upon delete of unnumbered neighbor), RAs
will continue to be exchanged if the operator has explicitly enabled.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-10640
Reviewed By: CCR-4589
Testing Done: Various manual and automated (refer to defect)
2016-05-02 22:53:38 +02:00
|
|
|
#include "zebra/rtadv.h"
|
2016-06-01 19:19:30 +02:00
|
|
|
#include "zebra/zebra_mpls.h"
|
2016-08-11 02:04:20 +02:00
|
|
|
#include "zebra/zebra_mroute.h"
|
2017-03-20 15:34:49 +01:00
|
|
|
#include "zebra/label_manager.h"
|
2017-05-15 07:38:26 +02:00
|
|
|
#include "zebra/zebra_vxlan.h"
|
2017-06-13 14:59:32 +02:00
|
|
|
#include "zebra/rt.h"
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Event list of zebra. */
|
|
|
|
enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_event(enum event event, int sock, struct zserv *client);
|
2003-03-01 12:42:20 +01:00
|
|
|
|
2003-06-04 15:59:38 +02:00
|
|
|
extern struct zebra_privs_t zserv_privs;
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_client_close(struct zserv *client);
|
|
|
|
|
|
|
|
static int zserv_delayed_close(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct zserv *client = THREAD_ARG(thread);
|
|
|
|
|
|
|
|
client->t_suicide = NULL;
|
|
|
|
zebra_client_close(client);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int zserv_flush_data(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct zserv *client = THREAD_ARG(thread);
|
|
|
|
|
|
|
|
client->t_write = NULL;
|
|
|
|
if (client->t_suicide) {
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
switch (buffer_flush_available(client->wb, client->sock)) {
|
|
|
|
case BUFFER_ERROR:
|
|
|
|
zlog_warn(
|
|
|
|
"%s: buffer_flush_available failed on zserv client fd %d, "
|
|
|
|
"closing",
|
|
|
|
__func__, client->sock);
|
|
|
|
zebra_client_close(client);
|
|
|
|
client = NULL;
|
|
|
|
break;
|
|
|
|
case BUFFER_PENDING:
|
|
|
|
client->t_write = NULL;
|
|
|
|
thread_add_write(zebrad.master, zserv_flush_data, client,
|
|
|
|
client->sock, &client->t_write);
|
|
|
|
break;
|
|
|
|
case BUFFER_EMPTY:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (client)
|
|
|
|
client->last_write_time = monotime(NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int zebra_server_send_message(struct zserv *client)
|
|
|
|
{
|
|
|
|
if (client->t_suicide)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (client->is_synchronous)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
stream_set_getp(client->obuf, 0);
|
|
|
|
client->last_write_cmd = stream_getw_from(client->obuf, 6);
|
|
|
|
switch (buffer_write(client->wb, client->sock,
|
|
|
|
STREAM_DATA(client->obuf),
|
|
|
|
stream_get_endp(client->obuf))) {
|
|
|
|
case BUFFER_ERROR:
|
|
|
|
zlog_warn(
|
|
|
|
"%s: buffer_write failed to zserv client fd %d, closing",
|
|
|
|
__func__, client->sock);
|
|
|
|
/* Schedule a delayed close since many of the functions that
|
|
|
|
call this
|
|
|
|
one do not check the return code. They do not allow for the
|
|
|
|
possibility that an I/O error may have caused the client to
|
|
|
|
be
|
|
|
|
deleted. */
|
|
|
|
client->t_suicide = NULL;
|
|
|
|
thread_add_event(zebrad.master, zserv_delayed_close, client, 0,
|
|
|
|
&client->t_suicide);
|
|
|
|
return -1;
|
|
|
|
case BUFFER_EMPTY:
|
|
|
|
THREAD_OFF(client->t_write);
|
|
|
|
break;
|
|
|
|
case BUFFER_PENDING:
|
|
|
|
thread_add_write(zebrad.master, zserv_flush_data, client,
|
|
|
|
client->sock, &client->t_write);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
client->last_write_time = monotime(NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zserv_encode_interface(struct stream *s, struct interface *ifp)
|
|
|
|
{
|
|
|
|
/* Interface information. */
|
|
|
|
stream_put(s, ifp->name, INTERFACE_NAMSIZ);
|
|
|
|
stream_putl(s, ifp->ifindex);
|
|
|
|
stream_putc(s, ifp->status);
|
|
|
|
stream_putq(s, ifp->flags);
|
|
|
|
stream_putc(s, ifp->ptm_enable);
|
|
|
|
stream_putc(s, ifp->ptm_status);
|
|
|
|
stream_putl(s, ifp->metric);
|
|
|
|
stream_putl(s, ifp->speed);
|
|
|
|
stream_putl(s, ifp->mtu);
|
|
|
|
stream_putl(s, ifp->mtu6);
|
|
|
|
stream_putl(s, ifp->bandwidth);
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* Then, Traffic Engineering parameters if any */
|
|
|
|
if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) {
|
|
|
|
stream_putc(s, 1);
|
|
|
|
zebra_interface_link_params_write(s, ifp);
|
|
|
|
} else
|
|
|
|
stream_putc(s, 0);
|
|
|
|
|
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct vrf_data data;
|
|
|
|
|
|
|
|
data.l.table_id = zvrf->table_id;
|
|
|
|
/* Pass the tableid */
|
|
|
|
stream_put(s, &data, sizeof(struct vrf_data));
|
|
|
|
/* Interface information. */
|
|
|
|
stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ);
|
|
|
|
|
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2016-02-01 19:55:42 +01:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
|
2004-05-09 11:09:59 +02:00
|
|
|
/*
|
|
|
|
* This function is called in the following situations:
|
|
|
|
* - in response to a 3-byte ZEBRA_INTERFACE_ADD request
|
|
|
|
* from the client.
|
|
|
|
* - at startup, when zebra figures out the available interfaces
|
|
|
|
* - when an interface is added (where support for
|
|
|
|
* RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
|
|
|
|
* an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
|
|
|
|
* received)
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_add(struct zserv *client, struct interface *ifp)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
|
|
|
|
zserv_encode_interface(s, ifp);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->ifadd_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interface deletion from zebra daemon. */
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_delete(struct zserv *client, struct interface *ifp)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
|
|
|
|
zserv_encode_interface(s, ifp);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->ifdel_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf)
|
2016-02-01 19:55:42 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf));
|
|
|
|
zserv_encode_vrf(s, zvrf);
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->vrfadd_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2016-02-01 19:55:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* VRF deletion from zebra daemon. */
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf)
|
2016-02-01 19:55:42 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf));
|
|
|
|
zserv_encode_vrf(s, zvrf);
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->vrfdel_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2016-02-01 19:55:42 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Check this client need interface information. */
|
|
|
|
if (!client->ifinfo)
|
|
|
|
return 0;
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!ifp->link_params)
|
|
|
|
return 0;
|
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Add Interface Index */
|
|
|
|
stream_putl(s, ifp->ifindex);
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Then TE Link Parameters */
|
|
|
|
if (zebra_interface_link_params_write(s, ifp) == 0)
|
|
|
|
return 0;
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return zebra_server_send_message(client);
|
Update Traffic Engineering Support for OSPFD
NOTE: I am squashing several commits together because they
do not independently compile and we need this ability to
do any type of sane testing on the patches. Since this
series builds together I am doing this. -DBS
This new structure is the basis to get new link parameters for
Traffic Engineering from Zebra/interface layer to OSPFD and ISISD
for the support of Traffic Engineering
* lib/if.[c,h]: link parameters struture and get/set functions
* lib/command.[c,h]: creation of a new link-node
* lib/zclient.[c,h]: modification to the ZBUS message to convey the
link parameters structure
* lib/zebra.h: New ZBUS message
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support for IEEE 754 format
* lib/stream.[c,h]: Add stream_get{f,d} and stream_put{f,d}) demux and muxers to
safely convert between big-endian IEEE-754 single and double binary
format, as used in IETF RFCs, and C99. Implementation depends on host
using __STDC_IEC_559__, which should be everything we care about. Should
correctly error out otherwise.
* lib/network.[c,h]: Add ntohf and htonf converter
* lib/memtypes.c: Add new memeory type for Traffic Engineering support
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add link parameters support to Zebra
* zebra/interface.c:
- Add new link-params CLI commands
- Add new functions to set/get link parameters for interface
* zebra/redistribute.[c,h]: Add new function to propagate link parameters
to routing daemon (essentially OSPFD and ISISD) for Traffic Engineering.
* zebra/redistribute_null.c: Add new function
zebra_interface_parameters_update()
* zebra/zserv.[c,h]: Add new functions to send link parameters
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Add support of new link-params CLI to vtysh
In vtysh_config.c/vtysh_config_parse_line(), it is not possible to continue
to use the ordered version for adding line i.e. config_add_line_uniq() to print
Interface CLI commands as it completely break the new LINK_PARAMS_NODE.
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Update Traffic Engineering support for OSPFD
These patches update original code to RFC3630 (OSPF-TE) and add support of
RFC5392 (Inter-AS v2) & RFC7471 (TE metric extensions) and partial support
of RFC6827 (ASON - GMPLS).
* ospfd/ospf_dump.[c,h]: Add new dump functions for Traffic Engineering
* ospfd/ospf_opaque.[c,h]: Add new TLV code points for RFC5392
* ospfd/ospf_packet.c: Update checking of OSPF_OPTION
* ospfd/ospf_vty.[c,h]: Update ospf_str2area_id
* ospfd/ospf_zebra.c: Add new function ospf_interface_link_params() to get
Link Parameters information from the interface to populate Traffic Engineering
metrics
* ospfd/ospfd.[c,h]: Update OSPF_OPTION flags (T -> MT and new DN)
* ospfd/ospf_te.[c,h]: Major modifications to update the code to new
link parameters structure and new RFCs
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
tmp
2016-04-19 16:21:46 +02:00
|
|
|
}
|
|
|
|
|
2004-05-09 11:09:59 +02:00
|
|
|
/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
|
2017-07-17 14:03:14 +02:00
|
|
|
* ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
|
2004-05-09 11:09:59 +02:00
|
|
|
*
|
|
|
|
* A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
|
|
|
|
* - in response to a 3-byte ZEBRA_INTERFACE_ADD request
|
|
|
|
* from the client, after the ZEBRA_INTERFACE_ADD has been
|
|
|
|
* sent from zebra to the client
|
|
|
|
* - redistribute new address info to all clients in the following situations
|
|
|
|
* - at startup, when zebra figures out the available interfaces
|
|
|
|
* - when an interface is added (where support for
|
|
|
|
* RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
|
|
|
|
* an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
|
|
|
|
* received)
|
|
|
|
* - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
|
|
|
|
* and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
|
|
|
|
* - when an RTM_NEWADDR message is received from the kernel,
|
2017-07-17 14:03:14 +02:00
|
|
|
*
|
|
|
|
* The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
|
2004-05-09 11:09:59 +02:00
|
|
|
*
|
|
|
|
* zsend_interface_address(DELETE)
|
2017-07-17 14:03:14 +02:00
|
|
|
* ^
|
|
|
|
* |
|
|
|
|
* zebra_interface_address_delete_update
|
2004-05-09 11:09:59 +02:00
|
|
|
* ^ ^ ^
|
2005-07-29 16:36:00 +02:00
|
|
|
* | | if_delete_update
|
|
|
|
* | |
|
2004-05-09 11:09:59 +02:00
|
|
|
* ip_address_uninstall connected_delete_ipv4
|
|
|
|
* [ipv6_addresss_uninstall] [connected_delete_ipv6]
|
|
|
|
* ^ ^
|
|
|
|
* | |
|
|
|
|
* | RTM_NEWADDR on routing/netlink socket
|
|
|
|
* |
|
|
|
|
* vty commands:
|
|
|
|
* "no ip address A.B.C.D/M [label LINE]"
|
|
|
|
* "no ip address A.B.C.D/M secondary"
|
|
|
|
* ["no ipv6 address X:X::X:X/M"]
|
|
|
|
*
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_address(int cmd, struct zserv *client,
|
|
|
|
struct interface *ifp, struct connected *ifc)
|
|
|
|
{
|
|
|
|
int blen;
|
|
|
|
struct stream *s;
|
|
|
|
struct prefix *p;
|
|
|
|
|
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
|
|
|
|
|
|
|
zserv_create_header(s, cmd, ifp->vrf_id);
|
|
|
|
stream_putl(s, ifp->ifindex);
|
|
|
|
|
|
|
|
/* Interface address flag. */
|
|
|
|
stream_putc(s, ifc->flags);
|
|
|
|
|
|
|
|
/* Prefix information. */
|
|
|
|
p = ifc->address;
|
|
|
|
stream_putc(s, p->family);
|
|
|
|
blen = prefix_blen(p);
|
|
|
|
stream_put(s, &p->u.prefix, blen);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX gnu version does not send prefixlen for
|
|
|
|
* ZEBRA_INTERFACE_ADDRESS_DELETE
|
|
|
|
* but zebra_interface_address_delete_read() in the gnu version
|
|
|
|
* expects to find it
|
|
|
|
*/
|
|
|
|
stream_putc(s, p->prefixlen);
|
|
|
|
|
|
|
|
/* Destination. */
|
|
|
|
p = ifc->destination;
|
|
|
|
if (p)
|
|
|
|
stream_put(s, &p->u.prefix, blen);
|
|
|
|
else
|
|
|
|
stream_put(s, NULL, blen);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->connected_rt_add_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zsend_interface_nbr_address(int cmd, struct zserv *client,
|
|
|
|
struct interface *ifp,
|
|
|
|
struct nbr_connected *ifc)
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int blen;
|
|
|
|
struct stream *s;
|
|
|
|
struct prefix *p;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, cmd, ifp->vrf_id);
|
|
|
|
stream_putl(s, ifp->ifindex);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Prefix information. */
|
|
|
|
p = ifc->address;
|
|
|
|
stream_putc(s, p->family);
|
|
|
|
blen = prefix_blen(p);
|
|
|
|
stream_put(s, &p->u.prefix, blen);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/*
|
|
|
|
* XXX gnu version does not send prefixlen for
|
|
|
|
* ZEBRA_INTERFACE_ADDRESS_DELETE
|
|
|
|
* but zebra_interface_address_delete_read() in the gnu version
|
|
|
|
* expects to find it
|
|
|
|
*/
|
|
|
|
stream_putc(s, p->prefixlen);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return zebra_server_send_message(client);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interface address addition. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_interface_nbr_address_add_update(struct interface *ifp,
|
|
|
|
struct nbr_connected *ifc)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct zserv *client;
|
|
|
|
struct prefix *p;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT) {
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
|
|
|
p = ifc->address;
|
|
|
|
zlog_debug(
|
|
|
|
"MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s",
|
|
|
|
inet_ntop(p->family, &p->u.prefix, buf,
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
p->prefixlen, ifc->ifp->name);
|
|
|
|
}
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
|
|
|
zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
|
|
|
client, ifp, ifc);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interface address deletion. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_interface_nbr_address_delete_update(struct interface *ifp,
|
|
|
|
struct nbr_connected *ifc)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct zserv *client;
|
|
|
|
struct prefix *p;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT) {
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
|
|
|
p = ifc->address;
|
|
|
|
zlog_debug(
|
|
|
|
"MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s",
|
|
|
|
inet_ntop(p->family, &p->u.prefix, buf,
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
p->prefixlen, ifc->ifp->name);
|
|
|
|
}
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
|
|
|
|
zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
|
|
|
|
client, ifp, ifc);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
2016-02-25 20:30:53 +01:00
|
|
|
/* Send addresses on interface to client */
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
|
2016-02-25 20:30:53 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct listnode *cnode, *cnnode;
|
|
|
|
struct connected *c;
|
|
|
|
struct nbr_connected *nc;
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Send interface addresses. */
|
|
|
|
for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
|
|
|
|
if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
|
|
|
|
continue;
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, client,
|
|
|
|
ifp, c)
|
|
|
|
< 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Send interface neighbors. */
|
|
|
|
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, cnode, cnnode, nc)) {
|
|
|
|
if (zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
|
|
|
client, ifp, nc)
|
|
|
|
< 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2016-02-25 20:30:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Notify client about interface moving from one VRF to another.
|
|
|
|
* Whether client is interested in old and new VRF is checked by caller.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
|
|
|
|
vrf_id_t vrf_id)
|
2016-02-25 20:30:53 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Fill in the ifIndex of the interface and its new VRF (id) */
|
|
|
|
stream_putl(s, ifp->ifindex);
|
|
|
|
stream_putw(s, vrf_id);
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2016-02-25 20:30:53 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->if_vrfchg_cnt++;
|
|
|
|
return zebra_server_send_message(client);
|
2016-02-25 20:30:53 +01:00
|
|
|
}
|
|
|
|
|
2016-05-13 07:57:40 +02:00
|
|
|
/* Add new nbr connected IPv6 address */
|
2017-07-17 14:03:14 +02:00
|
|
|
void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address)
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct nbr_connected *ifc;
|
|
|
|
struct prefix p;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET6;
|
|
|
|
IPV6_ADDR_COPY(&p.u.prefix, address);
|
|
|
|
p.prefixlen = IPV6_MAX_PREFIXLEN;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!(ifc = listnode_head(ifp->nbr_connected))) {
|
|
|
|
/* new addition */
|
|
|
|
ifc = nbr_connected_new();
|
|
|
|
ifc->address = prefix_new();
|
|
|
|
ifc->ifp = ifp;
|
|
|
|
listnode_add(ifp->nbr_connected, ifc);
|
|
|
|
}
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
prefix_copy(ifc->address, &p);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zebra_interface_nbr_address_add_update(ifp, ifc);
|
2015-06-11 18:19:59 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 1);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address)
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct nbr_connected *ifc;
|
|
|
|
struct prefix p;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET6;
|
|
|
|
IPV6_ADDR_COPY(&p.u.prefix, address);
|
|
|
|
p.prefixlen = IPV6_MAX_PREFIXLEN;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ifc = nbr_connected_check(ifp, &p);
|
|
|
|
if (!ifc)
|
|
|
|
return;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
listnode_delete(ifp->nbr_connected, ifc);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zebra_interface_nbr_address_delete_update(ifp, ifc);
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 0);
|
2015-06-11 18:19:59 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
nbr_connected_free(ifc);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
2004-05-09 11:09:59 +02:00
|
|
|
/*
|
|
|
|
* The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
|
|
|
|
* ZEBRA_INTERFACE_DOWN.
|
|
|
|
*
|
|
|
|
* The ZEBRA_INTERFACE_UP message is sent from the zebra server to
|
|
|
|
* the clients in one of 2 situations:
|
|
|
|
* - an if_up is detected e.g., as a result of an RTM_IFINFO message
|
|
|
|
* - a vty command modifying the bandwidth of an interface is received.
|
|
|
|
* The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, cmd, ifp->vrf_id);
|
|
|
|
zserv_encode_interface(s, ifp);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (cmd == ZEBRA_INTERFACE_UP)
|
|
|
|
client->ifup_cnt++;
|
|
|
|
else
|
|
|
|
client->ifdown_cnt++;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return zebra_server_send_message(client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix *src_p, struct route_entry *re)
|
|
|
|
{
|
2017-08-21 03:10:50 +02:00
|
|
|
struct zapi_route api;
|
|
|
|
struct zapi_nexthop *api_nh;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct nexthop *nexthop;
|
2017-08-21 03:10:50 +02:00
|
|
|
int count = 0;
|
2015-10-21 06:38:38 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
memset(&api, 0, sizeof(api));
|
2017-09-12 20:03:07 +02:00
|
|
|
api.vrf_id = re->vrf_id;
|
2017-08-21 03:10:50 +02:00
|
|
|
api.type = re->type;
|
|
|
|
api.instance = re->instance;
|
|
|
|
api.flags = re->flags;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Prefix. */
|
2017-08-21 03:10:50 +02:00
|
|
|
api.prefix = *p;
|
2017-07-17 14:03:14 +02:00
|
|
|
if (src_p) {
|
2017-08-21 03:10:50 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
|
|
|
|
memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
|
2015-05-20 03:04:20 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
/* Nexthops. */
|
|
|
|
if (re->nexthop_active_num) {
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
|
|
|
api.nexthop_num = re->nexthop_active_num;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) {
|
2017-08-21 03:10:50 +02:00
|
|
|
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
api_nh = &api.nexthops[count];
|
|
|
|
api_nh->type = nexthop->type;
|
|
|
|
switch (nexthop->type) {
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
2017-08-28 06:01:13 +02:00
|
|
|
api_nh->bh_type = nexthop->bh_type;
|
2017-08-21 03:10:50 +02:00
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
api_nh->gate.ipv4 = nexthop->gate.ipv4;
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
api_nh->gate.ipv4 = nexthop->gate.ipv4;
|
|
|
|
api_nh->ifindex = nexthop->ifindex;
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
api_nh->ifindex = nexthop->ifindex;
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
api_nh->gate.ipv6 = nexthop->gate.ipv6;
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
api_nh->gate.ipv6 = nexthop->gate.ipv6;
|
|
|
|
api_nh->ifindex = nexthop->ifindex;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-08-21 03:10:50 +02:00
|
|
|
count++;
|
2015-05-20 03:04:20 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
/* Attributes. */
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
|
|
|
api.distance = re->distance;
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
|
|
|
api.metric = re->metric;
|
2017-07-17 14:03:14 +02:00
|
|
|
if (re->tag) {
|
2017-08-21 03:10:50 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
|
|
|
api.tag = re->tag;
|
2015-05-20 03:04:20 +02:00
|
|
|
}
|
2017-08-21 03:10:50 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
|
|
|
|
api.mtu = re->mtu;
|
2015-05-20 03:04:20 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
/* Encode route and send. */
|
|
|
|
if (zapi_route_encode(cmd, client->obuf, &api) < 0)
|
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
return zebra_server_send_message(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop)
|
|
|
|
{
|
|
|
|
stream_putc(s, nexthop->type);
|
|
|
|
switch (nexthop->type) {
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
stream_put_in_addr(s, &nexthop->gate.ipv4);
|
|
|
|
stream_putl(s, nexthop->ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
stream_put(s, &nexthop->gate.ipv6, 16);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
stream_put(s, &nexthop->gate.ipv6, 16);
|
|
|
|
stream_putl(s, nexthop->ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
stream_putl(s, nexthop->ifindex);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* do nothing */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 1;
|
2015-05-20 02:40:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Nexthop register */
|
2017-10-11 14:31:35 +02:00
|
|
|
static int zserv_rnh_register(struct zserv *client, u_short length,
|
2017-07-17 14:03:14 +02:00
|
|
|
rnh_type_t type, struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct rnh *rnh;
|
|
|
|
struct stream *s;
|
|
|
|
struct prefix p;
|
|
|
|
u_short l = 0;
|
|
|
|
u_char flags = 0;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_NHT)
|
|
|
|
zlog_debug(
|
|
|
|
"rnh_register msg from client %s: length=%d, type=%s\n",
|
|
|
|
zebra_route_string(client->proto), length,
|
|
|
|
(type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route");
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
client->nh_reg_time = monotime(NULL);
|
|
|
|
|
|
|
|
while (l < length) {
|
|
|
|
flags = stream_getc(s);
|
|
|
|
p.family = stream_getw(s);
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
l += 4;
|
|
|
|
if (p.family == AF_INET) {
|
|
|
|
p.u.prefix4.s_addr = stream_get_ipv4(s);
|
|
|
|
l += IPV4_MAX_BYTELEN;
|
|
|
|
} else if (p.family == AF_INET6) {
|
|
|
|
stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
|
|
|
|
l += IPV6_MAX_BYTELEN;
|
|
|
|
} else {
|
|
|
|
zlog_err(
|
|
|
|
"rnh_register: Received unknown family type %d\n",
|
|
|
|
p.family);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
|
|
|
|
if (type == RNH_NEXTHOP_TYPE) {
|
|
|
|
if (flags
|
|
|
|
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
|
|
|
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
|
|
|
else if (!flags
|
|
|
|
&& CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
|
|
|
UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
|
|
|
} else if (type == RNH_IMPORT_CHECK_TYPE) {
|
|
|
|
if (flags
|
|
|
|
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
|
|
|
|
SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
|
2017-07-22 14:52:33 +02:00
|
|
|
else if (!flags && CHECK_FLAG(rnh->flags,
|
|
|
|
ZEBRA_NHT_EXACT_MATCH))
|
2017-07-17 14:03:14 +02:00
|
|
|
UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
|
|
|
|
}
|
|
|
|
|
|
|
|
zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
|
|
|
|
/* Anything not AF_INET/INET6 has been filtered out above */
|
|
|
|
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
|
2015-05-20 03:04:20 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Nexthop register */
|
2017-10-11 14:31:35 +02:00
|
|
|
static int zserv_rnh_unregister(struct zserv *client, u_short length,
|
2017-07-17 14:03:14 +02:00
|
|
|
rnh_type_t type, struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct rnh *rnh;
|
|
|
|
struct stream *s;
|
|
|
|
struct prefix p;
|
|
|
|
u_short l = 0;
|
|
|
|
|
|
|
|
if (IS_ZEBRA_DEBUG_NHT)
|
|
|
|
zlog_debug("rnh_unregister msg from client %s: length=%d\n",
|
|
|
|
zebra_route_string(client->proto), length);
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
while (l < length) {
|
|
|
|
(void)stream_getc(
|
|
|
|
s); // Connected or not. Not used in this function
|
|
|
|
p.family = stream_getw(s);
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
l += 4;
|
|
|
|
if (p.family == AF_INET) {
|
|
|
|
p.u.prefix4.s_addr = stream_get_ipv4(s);
|
|
|
|
l += IPV4_MAX_BYTELEN;
|
|
|
|
} else if (p.family == AF_INET6) {
|
|
|
|
stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
|
|
|
|
l += IPV6_MAX_BYTELEN;
|
|
|
|
} else {
|
|
|
|
zlog_err(
|
|
|
|
"rnh_register: Received unknown family type %d\n",
|
|
|
|
p.family);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
|
|
|
|
if (rnh) {
|
|
|
|
client->nh_dereg_time = monotime(NULL);
|
|
|
|
zebra_remove_rnh_client(rnh, client, type);
|
|
|
|
}
|
2015-05-20 02:47:22 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2015-05-20 02:40:34 +02:00
|
|
|
}
|
|
|
|
|
2017-05-10 15:41:07 +02:00
|
|
|
#define ZEBRA_MIN_FEC_LENGTH 5
|
2017-04-15 19:25:03 +02:00
|
|
|
|
2017-02-01 19:10:56 +01:00
|
|
|
/* FEC register */
|
2017-10-11 14:31:35 +02:00
|
|
|
static int zserv_fec_register(struct zserv *client, u_short length)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zebra_vrf *zvrf;
|
|
|
|
u_short l = 0;
|
|
|
|
struct prefix p;
|
|
|
|
u_int16_t flags;
|
|
|
|
u_int32_t label_index = MPLS_INVALID_LABEL_INDEX;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
|
|
|
if (!zvrf)
|
|
|
|
return 0; // unexpected
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The minimum amount of data that can be sent for one fec
|
|
|
|
* registration
|
|
|
|
*/
|
|
|
|
if (length < ZEBRA_MIN_FEC_LENGTH) {
|
|
|
|
zlog_err(
|
|
|
|
"fec_register: Received a fec register of length %d, it is of insufficient size to properly decode",
|
|
|
|
length);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (l < length) {
|
|
|
|
flags = stream_getw(s);
|
2017-09-20 05:02:50 +02:00
|
|
|
memset(&p, 0, sizeof(p));
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = stream_getw(s);
|
|
|
|
if (p.family != AF_INET && p.family != AF_INET6) {
|
|
|
|
zlog_err(
|
|
|
|
"fec_register: Received unknown family type %d\n",
|
|
|
|
p.family);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
l += 5;
|
|
|
|
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
|
|
|
|
l += PSIZE(p.prefixlen);
|
|
|
|
if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) {
|
|
|
|
label_index = stream_getl(s);
|
|
|
|
l += 4;
|
|
|
|
} else
|
|
|
|
label_index = MPLS_INVALID_LABEL_INDEX;
|
|
|
|
zebra_mpls_fec_register(zvrf, &p, label_index, client);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-02-01 19:10:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FEC unregister */
|
2017-10-11 14:31:35 +02:00
|
|
|
static int zserv_fec_unregister(struct zserv *client, u_short length)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zebra_vrf *zvrf;
|
|
|
|
u_short l = 0;
|
|
|
|
struct prefix p;
|
|
|
|
// u_int16_t flags;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
|
|
|
if (!zvrf)
|
|
|
|
return 0; // unexpected
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The minimum amount of data that can be sent for one
|
|
|
|
* fec unregistration
|
|
|
|
*/
|
|
|
|
if (length < ZEBRA_MIN_FEC_LENGTH) {
|
|
|
|
zlog_err(
|
|
|
|
"fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode",
|
|
|
|
length);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (l < length) {
|
|
|
|
// flags = stream_getw(s);
|
|
|
|
(void)stream_getw(s);
|
2017-09-20 05:02:50 +02:00
|
|
|
memset(&p, 0, sizeof(p));
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = stream_getw(s);
|
|
|
|
if (p.family != AF_INET && p.family != AF_INET6) {
|
|
|
|
zlog_err(
|
|
|
|
"fec_unregister: Received unknown family type %d\n",
|
|
|
|
p.family);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
l += 5;
|
|
|
|
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
|
|
|
|
l += PSIZE(p.prefixlen);
|
|
|
|
zebra_mpls_fec_unregister(zvrf, &p, client);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-02-01 19:10:56 +01:00
|
|
|
}
|
|
|
|
|
2014-07-01 20:15:52 +02:00
|
|
|
/*
|
|
|
|
Modified version of zsend_ipv4_nexthop_lookup():
|
|
|
|
Query unicast rib if nexthop is not found on mrib.
|
|
|
|
Returns both route metric and protocol distance.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
|
|
|
|
struct in_addr addr,
|
|
|
|
struct route_entry *re,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
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, zvrf_id(zvrf));
|
|
|
|
stream_put_in_addr(s, &addr);
|
|
|
|
|
|
|
|
if (re) {
|
|
|
|
stream_putc(s, re->distance);
|
|
|
|
stream_putl(s, re->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 = re->nexthop; nexthop; nexthop = nexthop->next)
|
|
|
|
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
|
|
|
num += zsend_write_nexthop(s, nexthop);
|
|
|
|
|
|
|
|
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);
|
2014-07-01 20:15:52 +02:00
|
|
|
}
|
|
|
|
|
2004-10-03 20:18:34 +02:00
|
|
|
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
|
2017-07-17 14:03:14 +02:00
|
|
|
int zsend_router_id_update(struct zserv *client, struct prefix *p,
|
|
|
|
vrf_id_t vrf_id)
|
2004-10-03 20:18:34 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
int blen;
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Check this client need interface information. */
|
|
|
|
if (!vrf_bitmap_check(client->ridinfo, vrf_id))
|
|
|
|
return 0;
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Message type. */
|
|
|
|
zserv_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Prefix information. */
|
|
|
|
stream_putc(s, p->family);
|
|
|
|
blen = prefix_blen(p);
|
|
|
|
stream_put(s, &p->u.prefix, blen);
|
|
|
|
stream_putc(s, p->prefixlen);
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return zebra_server_send_message(client);
|
2004-10-03 20:18:34 +02:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2017-05-15 17:09:28 +02:00
|
|
|
/*
|
|
|
|
* Function used by Zebra to send a PW status update to LDP daemon
|
|
|
|
*/
|
|
|
|
int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
|
|
|
|
|
|
|
zserv_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
|
|
|
|
stream_write(s, pw->ifname, IF_NAMESIZE);
|
|
|
|
stream_putl(s, pw->ifindex);
|
|
|
|
stream_putl(s, pw->status);
|
|
|
|
|
|
|
|
/* Put length at the first point of the stream. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
|
|
|
|
|
|
|
return zebra_server_send_message(client);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Register zebra server interface information. Send current all
|
|
|
|
interface and address information. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_interface_add(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct vrf *vrf;
|
|
|
|
struct interface *ifp;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Interface information is needed. */
|
|
|
|
vrf_bitmap_set(client->ifinfo, zvrf_id(zvrf));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-09-15 17:47:35 +02:00
|
|
|
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
|
2017-10-06 20:25:58 +02:00
|
|
|
FOR_ALL_INTERFACES (vrf, ifp) {
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Skip pseudo interface. */
|
|
|
|
if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
|
|
|
|
continue;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zsend_interface_add(client, ifp) < 0)
|
|
|
|
return -1;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zsend_interface_addresses(client, ifp) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Unregister zebra server interface information. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_interface_delete(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
|
|
|
|
const unsigned int nexthop_num)
|
2015-09-16 14:30:23 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (nexthop_num > multipath_num) {
|
|
|
|
char buff[PREFIX2STR_BUFFER];
|
|
|
|
prefix2str(p, buff, sizeof(buff));
|
|
|
|
zlog_warn(
|
|
|
|
"%s: Prefix %s has %d nexthops, but we can only use the first %d",
|
|
|
|
caller, buff, nexthop_num, multipath_num);
|
|
|
|
}
|
2015-09-16 14:30:23 +02:00
|
|
|
}
|
|
|
|
|
2017-08-20 02:59:41 +02:00
|
|
|
static int zread_route_add(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zapi_route api;
|
|
|
|
struct zapi_nexthop *api_nh;
|
|
|
|
afi_t afi;
|
|
|
|
struct prefix_ipv6 *src_p = NULL;
|
|
|
|
struct route_entry *re;
|
2017-08-24 14:02:27 +02:00
|
|
|
struct nexthop *nexthop = NULL;
|
2017-08-20 02:59:41 +02:00
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
if (zapi_route_decode(s, &api) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Allocate new route. */
|
|
|
|
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
|
|
|
re->type = api.type;
|
|
|
|
re->instance = api.instance;
|
|
|
|
re->flags = api.flags;
|
|
|
|
re->uptime = time(NULL);
|
|
|
|
re->vrf_id = zvrf_id(zvrf);
|
|
|
|
re->table = zvrf->table_id;
|
|
|
|
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
|
|
|
|
for (i = 0; i < api.nexthop_num; i++) {
|
|
|
|
api_nh = &api.nexthops[i];
|
|
|
|
|
|
|
|
switch (api_nh->type) {
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
route_entry_nexthop_ifindex_add(
|
|
|
|
re, api_nh->ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
nexthop = route_entry_nexthop_ipv4_add(
|
|
|
|
re, &api_nh->gate.ipv4, NULL);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
|
|
|
re, &api_nh->gate.ipv4, NULL,
|
|
|
|
api_nh->ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
nexthop = route_entry_nexthop_ipv6_add(
|
|
|
|
re, &api_nh->gate.ipv6);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
|
|
|
re, &api_nh->gate.ipv6,
|
|
|
|
api_nh->ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
2017-08-30 17:23:01 +02:00
|
|
|
route_entry_nexthop_blackhole_add(
|
|
|
|
re, api_nh->bh_type);
|
2017-08-20 02:59:41 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MPLS labels for BGP-LU or Segment Routing */
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)
|
|
|
|
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
|
|
|
|
&& api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
|
|
|
|
enum lsp_types_t label_type;
|
|
|
|
|
|
|
|
label_type =
|
|
|
|
lsp_type_from_re_type(client->proto);
|
2017-08-21 00:57:36 +02:00
|
|
|
nexthop_add_labels(nexthop, label_type,
|
|
|
|
api_nh->label_num,
|
|
|
|
&api_nh->labels[0]);
|
2017-08-20 02:59:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
|
|
|
|
re->distance = api.distance;
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
|
|
|
|
re->metric = api.metric;
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
|
|
|
|
re->tag = api.tag;
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
|
|
|
|
re->mtu = api.mtu;
|
|
|
|
|
|
|
|
afi = family2afi(api.prefix.family);
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
|
|
|
src_p = &api.src_prefix;
|
|
|
|
|
|
|
|
ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re);
|
|
|
|
|
|
|
|
/* Stats */
|
|
|
|
switch (api.prefix.family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (ret > 0)
|
|
|
|
client->v4_route_add_cnt++;
|
|
|
|
else if (ret < 0)
|
|
|
|
client->v4_route_upd8_cnt++;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (ret > 0)
|
|
|
|
client->v6_route_add_cnt++;
|
|
|
|
else if (ret < 0)
|
|
|
|
client->v6_route_upd8_cnt++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int zread_route_del(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zapi_route api;
|
|
|
|
afi_t afi;
|
|
|
|
struct prefix_ipv6 *src_p = NULL;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
if (zapi_route_decode(s, &api) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
afi = family2afi(api.prefix.family);
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
|
|
|
src_p = &api.src_prefix;
|
|
|
|
|
|
|
|
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
2010-02-05 04:31:56 +01:00
|
|
|
api.flags, &api.prefix, src_p, NULL, zvrf->table_id,
|
2017-09-25 18:28:39 +02:00
|
|
|
api.metric, false);
|
2017-08-20 02:59:41 +02:00
|
|
|
|
|
|
|
/* Stats */
|
|
|
|
switch (api.prefix.family) {
|
|
|
|
case AF_INET:
|
|
|
|
client->v4_route_del_cnt++;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
client->v6_route_del_cnt++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* This function support multiple nexthop. */
|
2017-07-17 14:03:14 +02:00
|
|
|
/*
|
2017-06-01 13:26:25 +02:00
|
|
|
* Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
|
2017-07-17 14:03:14 +02:00
|
|
|
* add kernel route.
|
2004-05-09 11:09:59 +02:00
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_ipv4_add(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct route_entry *re;
|
|
|
|
struct prefix p;
|
|
|
|
u_char message;
|
|
|
|
struct in_addr nhop_addr;
|
|
|
|
u_char nexthop_num;
|
|
|
|
u_char nexthop_type;
|
|
|
|
struct stream *s;
|
|
|
|
ifindex_t ifindex;
|
|
|
|
safi_t safi;
|
|
|
|
int ret;
|
2017-08-26 01:14:25 +02:00
|
|
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
2017-07-17 14:03:14 +02:00
|
|
|
mpls_label_t label;
|
|
|
|
struct nexthop *nexthop;
|
2010-02-05 04:31:56 +01:00
|
|
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Allocate new re. */
|
|
|
|
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
|
|
|
|
|
|
|
/* Type, flags, message. */
|
|
|
|
re->type = stream_getc(s);
|
|
|
|
re->instance = stream_getw(s);
|
|
|
|
re->flags = stream_getl(s);
|
|
|
|
message = stream_getc(s);
|
|
|
|
safi = stream_getw(s);
|
|
|
|
re->uptime = time(NULL);
|
|
|
|
|
|
|
|
/* IPv4 prefix. */
|
|
|
|
memset(&p, 0, sizeof(struct prefix_ipv4));
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
|
|
|
|
|
|
|
/* VRF ID */
|
|
|
|
re->vrf_id = zvrf_id(zvrf);
|
|
|
|
|
|
|
|
/* Nexthop parse. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
|
|
|
nexthop_num = stream_getc(s);
|
|
|
|
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
|
|
|
nexthop_num);
|
|
|
|
|
2017-08-20 01:00:25 +02:00
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
|
|
|
label_type = lsp_type_from_re_type(client->proto);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (i = 0; i < nexthop_num; i++) {
|
|
|
|
nexthop_type = stream_getc(s);
|
|
|
|
|
|
|
|
switch (nexthop_type) {
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
route_entry_nexthop_ifindex_add(re, ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
nhop_addr.s_addr = stream_get_ipv4(s);
|
|
|
|
nexthop = route_entry_nexthop_ipv4_add(
|
|
|
|
re, &nhop_addr, NULL);
|
|
|
|
/* For labeled-unicast, each nexthop is followed
|
|
|
|
* by label. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
|
|
|
|
label = (mpls_label_t)stream_getl(s);
|
2017-08-20 01:00:25 +02:00
|
|
|
nexthop_add_labels(nexthop, label_type,
|
|
|
|
1, &label);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
nhop_addr.s_addr = stream_get_ipv4(s);
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
route_entry_nexthop_ipv4_ifindex_add(
|
|
|
|
re, &nhop_addr, NULL, ifindex);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
stream_forward_getp(s, IPV6_MAX_BYTELEN);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
2010-02-05 04:31:56 +01:00
|
|
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Distance. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
|
|
|
re->distance = stream_getc(s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Metric. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
|
|
|
re->metric = stream_getl(s);
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Tag */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
|
|
|
re->tag = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->tag = 0;
|
2015-11-02 15:50:07 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
|
|
|
re->mtu = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->mtu = 0;
|
|
|
|
|
|
|
|
/* Table */
|
|
|
|
re->table = zvrf->table_id;
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re);
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Stats */
|
|
|
|
if (ret > 0)
|
|
|
|
client->v4_route_add_cnt++;
|
|
|
|
else if (ret < 0)
|
|
|
|
client->v4_route_upd8_cnt++;
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Zebra server IPv4 prefix delete function. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_ipv4_delete(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zapi_ipv4 api;
|
|
|
|
struct prefix p;
|
|
|
|
u_int32_t table_id;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Type, flags, message. */
|
|
|
|
api.type = stream_getc(s);
|
|
|
|
api.instance = stream_getw(s);
|
|
|
|
api.flags = stream_getl(s);
|
|
|
|
api.message = stream_getc(s);
|
|
|
|
api.safi = stream_getw(s);
|
|
|
|
|
|
|
|
/* IPv4 prefix. */
|
|
|
|
memset(&p, 0, sizeof(struct prefix));
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
|
|
|
|
|
|
|
table_id = zvrf->table_id;
|
|
|
|
|
|
|
|
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
2017-09-25 18:28:39 +02:00
|
|
|
api.flags, &p, NULL, NULL, table_id, 0, false);
|
2017-07-17 14:03:14 +02:00
|
|
|
client->v4_route_del_cnt++;
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-07-01 20:15:52 +02:00
|
|
|
/* MRIB Nexthop lookup for IPv4. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2014-07-01 20:15:52 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in_addr addr;
|
|
|
|
struct route_entry *re;
|
2014-07-01 20:15:52 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
addr.s_addr = stream_get_ipv4(client->ibuf);
|
|
|
|
re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL);
|
|
|
|
return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);
|
2014-07-01 20:15:52 +02:00
|
|
|
}
|
|
|
|
|
2015-06-11 18:19:12 +02:00
|
|
|
/* Zebra server IPv6 prefix add function. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
|
|
|
u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct stream *s;
|
|
|
|
struct in6_addr nhop_addr;
|
|
|
|
struct route_entry *re;
|
|
|
|
u_char message;
|
|
|
|
u_char nexthop_num;
|
|
|
|
u_char nexthop_type;
|
|
|
|
struct prefix p;
|
|
|
|
safi_t safi;
|
|
|
|
static struct in6_addr nexthops[MULTIPATH_NUM];
|
|
|
|
static unsigned int ifindices[MULTIPATH_NUM];
|
|
|
|
int ret;
|
|
|
|
static mpls_label_t labels[MULTIPATH_NUM];
|
2017-08-24 14:02:27 +02:00
|
|
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
2017-07-17 14:03:14 +02:00
|
|
|
mpls_label_t label;
|
|
|
|
struct nexthop *nexthop;
|
2010-02-05 04:31:56 +01:00
|
|
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
memset(&nhop_addr, 0, sizeof(struct in6_addr));
|
|
|
|
|
|
|
|
/* Allocate new re. */
|
|
|
|
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
|
|
|
|
|
|
|
/* Type, flags, message. */
|
|
|
|
re->type = stream_getc(s);
|
|
|
|
re->instance = stream_getw(s);
|
|
|
|
re->flags = stream_getl(s);
|
|
|
|
message = stream_getc(s);
|
|
|
|
safi = stream_getw(s);
|
|
|
|
re->uptime = time(NULL);
|
|
|
|
|
|
|
|
/* IPv4 prefix. */
|
|
|
|
memset(&p, 0, sizeof(struct prefix_ipv4));
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
|
|
|
|
|
|
|
/* VRF ID */
|
|
|
|
re->vrf_id = zvrf_id(zvrf);
|
|
|
|
|
|
|
|
/* We need to give nh-addr, nh-ifindex with the same next-hop object
|
|
|
|
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
|
|
|
* these. Clients should send the same number of paired set of
|
|
|
|
* next-hop-addr/next-hop-ifindices. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
|
|
|
unsigned int nh_count = 0;
|
|
|
|
unsigned int if_count = 0;
|
|
|
|
unsigned int max_nh_if = 0;
|
|
|
|
|
|
|
|
nexthop_num = stream_getc(s);
|
|
|
|
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
|
|
|
nexthop_num);
|
2017-08-20 01:00:25 +02:00
|
|
|
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
|
|
|
label_type = lsp_type_from_re_type(client->proto);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (i = 0; i < nexthop_num; i++) {
|
|
|
|
nexthop_type = stream_getc(s);
|
|
|
|
|
|
|
|
switch (nexthop_type) {
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
stream_get(&nhop_addr, s, 16);
|
|
|
|
if (nh_count < MULTIPATH_NUM) {
|
|
|
|
/* For labeled-unicast, each nexthop is
|
|
|
|
* followed by label. */
|
|
|
|
if (CHECK_FLAG(message,
|
|
|
|
ZAPI_MESSAGE_LABEL)) {
|
|
|
|
label = (mpls_label_t)
|
|
|
|
stream_getl(s);
|
|
|
|
labels[nh_count] = label;
|
|
|
|
}
|
|
|
|
nexthops[nh_count] = nhop_addr;
|
|
|
|
nh_count++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
if (if_count < multipath_num) {
|
|
|
|
ifindices[if_count++] = stream_getl(s);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
2010-02-05 04:31:56 +01:00
|
|
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
|
|
|
|
for (i = 0; i < max_nh_if; i++) {
|
|
|
|
if ((i < nh_count)
|
|
|
|
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
|
|
|
|
if ((i < if_count) && ifindices[i])
|
|
|
|
nexthop =
|
|
|
|
route_entry_nexthop_ipv6_ifindex_add(
|
|
|
|
re, &nexthops[i],
|
|
|
|
ifindices[i]);
|
|
|
|
else
|
|
|
|
nexthop = route_entry_nexthop_ipv6_add(
|
|
|
|
re, &nexthops[i]);
|
|
|
|
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
2017-08-20 01:00:25 +02:00
|
|
|
nexthop_add_labels(nexthop, label_type,
|
|
|
|
1, &labels[i]);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
|
|
|
if ((i < if_count) && ifindices[i])
|
|
|
|
route_entry_nexthop_ifindex_add(
|
|
|
|
re, ifindices[i]);
|
|
|
|
}
|
|
|
|
}
|
2015-06-11 18:19:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Distance. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
|
|
|
re->distance = stream_getc(s);
|
2015-05-20 02:24:43 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Metric. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
|
|
|
re->metric = stream_getl(s);
|
|
|
|
|
|
|
|
/* Tag */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
|
|
|
re->tag = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->tag = 0;
|
|
|
|
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
|
|
|
re->mtu = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->mtu = 0;
|
|
|
|
|
|
|
|
/* Table */
|
|
|
|
re->table = zvrf->table_id;
|
|
|
|
|
|
|
|
ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re);
|
|
|
|
/* Stats */
|
|
|
|
if (ret > 0)
|
|
|
|
client->v4_route_add_cnt++;
|
|
|
|
else if (ret < 0)
|
|
|
|
client->v4_route_upd8_cnt++;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int zread_ipv6_add(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct stream *s;
|
|
|
|
struct in6_addr nhop_addr;
|
2017-08-19 18:01:00 +02:00
|
|
|
ifindex_t ifindex;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_entry *re;
|
|
|
|
u_char message;
|
|
|
|
u_char nexthop_num;
|
|
|
|
u_char nexthop_type;
|
|
|
|
struct prefix p;
|
|
|
|
struct prefix_ipv6 src_p, *src_pp;
|
|
|
|
safi_t safi;
|
|
|
|
static struct in6_addr nexthops[MULTIPATH_NUM];
|
|
|
|
static unsigned int ifindices[MULTIPATH_NUM];
|
|
|
|
int ret;
|
|
|
|
static mpls_label_t labels[MULTIPATH_NUM];
|
2017-08-24 14:02:27 +02:00
|
|
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
2017-07-17 14:03:14 +02:00
|
|
|
mpls_label_t label;
|
|
|
|
struct nexthop *nexthop;
|
2010-02-05 04:31:56 +01:00
|
|
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
memset(&nhop_addr, 0, sizeof(struct in6_addr));
|
|
|
|
|
|
|
|
/* Allocate new re. */
|
|
|
|
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
|
|
|
|
|
|
|
/* Type, flags, message. */
|
|
|
|
re->type = stream_getc(s);
|
|
|
|
re->instance = stream_getw(s);
|
|
|
|
re->flags = stream_getl(s);
|
|
|
|
message = stream_getc(s);
|
|
|
|
safi = stream_getw(s);
|
|
|
|
re->uptime = time(NULL);
|
|
|
|
|
|
|
|
/* IPv6 prefix. */
|
|
|
|
memset(&p, 0, sizeof(struct prefix_ipv6));
|
|
|
|
p.family = AF_INET6;
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
|
|
|
|
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) {
|
|
|
|
memset(&src_p, 0, sizeof(struct prefix_ipv6));
|
|
|
|
src_p.family = AF_INET6;
|
|
|
|
src_p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
|
|
|
|
src_pp = &src_p;
|
|
|
|
} else
|
|
|
|
src_pp = NULL;
|
|
|
|
|
|
|
|
/* We need to give nh-addr, nh-ifindex with the same next-hop object
|
|
|
|
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
|
|
|
* these. Clients should send the same number of paired set of
|
|
|
|
* next-hop-addr/next-hop-ifindices. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
|
|
|
unsigned int nh_count = 0;
|
|
|
|
unsigned int if_count = 0;
|
|
|
|
unsigned int max_nh_if = 0;
|
|
|
|
|
|
|
|
nexthop_num = stream_getc(s);
|
|
|
|
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
|
|
|
nexthop_num);
|
2017-08-20 01:00:25 +02:00
|
|
|
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
|
|
|
label_type = lsp_type_from_re_type(client->proto);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (i = 0; i < nexthop_num; i++) {
|
|
|
|
nexthop_type = stream_getc(s);
|
|
|
|
|
|
|
|
switch (nexthop_type) {
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
stream_get(&nhop_addr, s, 16);
|
|
|
|
if (nh_count < MULTIPATH_NUM) {
|
|
|
|
/* For labeled-unicast, each nexthop is
|
|
|
|
* followed by label. */
|
|
|
|
if (CHECK_FLAG(message,
|
|
|
|
ZAPI_MESSAGE_LABEL)) {
|
|
|
|
label = (mpls_label_t)
|
|
|
|
stream_getl(s);
|
|
|
|
labels[nh_count] = label;
|
|
|
|
}
|
|
|
|
nexthops[nh_count++] = nhop_addr;
|
|
|
|
}
|
|
|
|
break;
|
2017-08-19 18:01:00 +02:00
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
stream_get(&nhop_addr, s, 16);
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
route_entry_nexthop_ipv6_ifindex_add(
|
|
|
|
re, &nhop_addr, ifindex);
|
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
if (if_count < multipath_num) {
|
|
|
|
ifindices[if_count++] = stream_getl(s);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_BLACKHOLE:
|
2010-02-05 04:31:56 +01:00
|
|
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
|
|
|
|
for (i = 0; i < max_nh_if; i++) {
|
|
|
|
if ((i < nh_count)
|
|
|
|
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
|
|
|
|
if ((i < if_count) && ifindices[i])
|
|
|
|
nexthop =
|
|
|
|
route_entry_nexthop_ipv6_ifindex_add(
|
|
|
|
re, &nexthops[i],
|
|
|
|
ifindices[i]);
|
|
|
|
else
|
|
|
|
nexthop = route_entry_nexthop_ipv6_add(
|
|
|
|
re, &nexthops[i]);
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
2017-08-20 01:00:25 +02:00
|
|
|
nexthop_add_labels(nexthop, label_type,
|
|
|
|
1, &labels[i]);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
|
|
|
if ((i < if_count) && ifindices[i])
|
|
|
|
route_entry_nexthop_ifindex_add(
|
|
|
|
re, ifindices[i]);
|
|
|
|
}
|
|
|
|
}
|
2015-05-20 02:24:43 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Distance. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
|
|
|
re->distance = stream_getc(s);
|
|
|
|
|
|
|
|
/* Metric. */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
|
|
|
re->metric = stream_getl(s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Tag */
|
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
|
|
|
re->tag = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->tag = 0;
|
2015-11-02 15:50:07 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
|
|
|
re->mtu = stream_getl(s);
|
|
|
|
else
|
|
|
|
re->mtu = 0;
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* VRF ID */
|
|
|
|
re->vrf_id = zvrf_id(zvrf);
|
|
|
|
re->table = zvrf->table_id;
|
2016-04-06 23:07:05 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);
|
|
|
|
/* Stats */
|
|
|
|
if (ret > 0)
|
|
|
|
client->v6_route_add_cnt++;
|
|
|
|
else if (ret < 0)
|
|
|
|
client->v6_route_upd8_cnt++;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Zebra server IPv6 prefix delete function. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_ipv6_delete(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zapi_ipv6 api;
|
|
|
|
struct prefix p;
|
|
|
|
struct prefix_ipv6 src_p, *src_pp;
|
|
|
|
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Type, flags, message. */
|
|
|
|
api.type = stream_getc(s);
|
|
|
|
api.instance = stream_getw(s);
|
|
|
|
api.flags = stream_getl(s);
|
|
|
|
api.message = stream_getc(s);
|
|
|
|
api.safi = stream_getw(s);
|
|
|
|
|
|
|
|
/* IPv4 prefix. */
|
2017-08-25 14:07:58 +02:00
|
|
|
memset(&p, 0, sizeof(struct prefix));
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET6;
|
|
|
|
p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
|
|
|
|
|
|
|
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
|
|
|
|
memset(&src_p, 0, sizeof(struct prefix_ipv6));
|
|
|
|
src_p.family = AF_INET6;
|
|
|
|
src_p.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
|
|
|
|
src_pp = &src_p;
|
|
|
|
} else
|
|
|
|
src_pp = NULL;
|
|
|
|
|
2017-08-19 19:26:00 +02:00
|
|
|
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
2017-09-25 18:28:39 +02:00
|
|
|
api.flags, &p, src_pp, NULL, client->rtm_table, 0, false);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
client->v6_route_del_cnt++;
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-10-03 20:18:34 +02:00
|
|
|
/* Register zebra server router-id information. Send current router-id */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_router_id_add(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2004-10-03 20:18:34 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix p;
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Router-id information is needed. */
|
|
|
|
vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf));
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
router_id_get(&p, zvrf_id(zvrf));
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return zsend_router_id_update(client, &p, zvrf_id(zvrf));
|
2004-10-03 20:18:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Unregister zebra server router-id information. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_router_id_delete(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2004-10-03 20:18:34 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
|
|
|
|
return 0;
|
2004-10-03 20:18:34 +02:00
|
|
|
}
|
|
|
|
|
2011-12-11 15:48:47 +01:00
|
|
|
/* Tie up route-type and client->sock */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zread_hello(struct zserv *client)
|
2011-12-11 15:48:47 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
/* type of protocol (lib/zebra.h) */
|
|
|
|
u_char proto;
|
|
|
|
u_short instance;
|
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
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
proto = stream_getc(client->ibuf);
|
|
|
|
instance = stream_getw(client->ibuf);
|
2011-12-11 15:48:47 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* 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 (instance)
|
|
|
|
zlog_notice("client protocol instance %d", instance);
|
2011-12-11 15:48:47 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->proto = proto;
|
|
|
|
client->instance = instance;
|
|
|
|
}
|
2011-12-11 15:48:47 +01:00
|
|
|
}
|
|
|
|
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
/* Unregister all information in a VRF. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zread_vrf_unregister(struct zserv *client, u_short length,
|
|
|
|
struct zebra_vrf *zvrf)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
afi_t afi;
|
|
|
|
|
|
|
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
|
|
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
|
|
|
vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
|
|
|
|
vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
|
|
|
|
vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
|
|
|
|
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zread_mpls_labels(int command, struct zserv *client, u_short length,
|
2017-10-11 14:41:29 +02:00
|
|
|
struct zebra_vrf *zvrf)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
enum lsp_types_t type;
|
|
|
|
struct prefix prefix;
|
|
|
|
enum nexthop_types_t gtype;
|
|
|
|
union g_addr gate;
|
|
|
|
ifindex_t ifindex;
|
|
|
|
mpls_label_t in_label, out_label;
|
|
|
|
u_int8_t distance;
|
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Get data. */
|
|
|
|
type = stream_getc(s);
|
|
|
|
prefix.family = stream_getl(s);
|
|
|
|
switch (prefix.family) {
|
|
|
|
case AF_INET:
|
|
|
|
prefix.u.prefix4.s_addr = stream_get_ipv4(s);
|
|
|
|
prefix.prefixlen = stream_getc(s);
|
|
|
|
gate.ipv4.s_addr = stream_get_ipv4(s);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
stream_get(&prefix.u.prefix6, s, 16);
|
|
|
|
prefix.prefixlen = stream_getc(s);
|
|
|
|
stream_get(&gate.ipv6, s, 16);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
distance = stream_getc(s);
|
|
|
|
in_label = stream_getl(s);
|
|
|
|
out_label = stream_getl(s);
|
|
|
|
|
|
|
|
switch (prefix.family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (ifindex)
|
|
|
|
gtype = NEXTHOP_TYPE_IPV4_IFINDEX;
|
|
|
|
else
|
|
|
|
gtype = NEXTHOP_TYPE_IPV4;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (ifindex)
|
|
|
|
gtype = NEXTHOP_TYPE_IPV6_IFINDEX;
|
|
|
|
else
|
|
|
|
gtype = NEXTHOP_TYPE_IPV6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mpls_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (command == ZEBRA_MPLS_LABELS_ADD) {
|
|
|
|
mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate,
|
|
|
|
ifindex);
|
2017-06-06 03:48:10 +02:00
|
|
|
mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex,
|
|
|
|
distance, out_label);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else if (command == ZEBRA_MPLS_LABELS_DELETE) {
|
|
|
|
mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex);
|
2017-06-06 03:48:10 +02:00
|
|
|
mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex,
|
|
|
|
distance, out_label);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2016-06-01 19:19:30 +02:00
|
|
|
}
|
2017-03-20 15:34:49 +01:00
|
|
|
/* Send response to a label manager connect request to client */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zsend_label_manager_connect_response(struct zserv *client,
|
|
|
|
vrf_id_t vrf_id, u_short result)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* result */
|
|
|
|
stream_putc(s, result);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return writen(client->sock, s->data, stream_get_endp(s));
|
2017-03-20 15:34:49 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
/* type of protocol (lib/zebra.h) */
|
|
|
|
u_char proto;
|
|
|
|
u_short instance;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Get data. */
|
|
|
|
proto = stream_getc(s);
|
|
|
|
instance = stream_getw(s);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* accept only dynamic routing protocols */
|
|
|
|
if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
|
|
|
|
zlog_err("client %d has wrong protocol %s", client->sock,
|
|
|
|
zebra_route_string(proto));
|
|
|
|
zsend_label_manager_connect_response(client, vrf_id, 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
zlog_notice("client %d with instance %u connected as %s", client->sock,
|
|
|
|
instance, zebra_route_string(proto));
|
|
|
|
client->proto = proto;
|
|
|
|
client->instance = instance;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Release previous labels of same protocol and instance.
|
|
|
|
This is done in case it restarted from an unexpected shutdown.
|
|
|
|
*/
|
|
|
|
release_daemon_chunks(proto, instance);
|
|
|
|
|
|
|
|
zlog_debug(
|
|
|
|
" Label Manager client connected: sock %d, proto %s, instance %u",
|
|
|
|
client->sock, zebra_route_string(proto), instance);
|
|
|
|
/* send response back */
|
|
|
|
zsend_label_manager_connect_response(client, vrf_id, 0);
|
2017-03-20 15:34:49 +01:00
|
|
|
}
|
|
|
|
/* Send response to a get label chunk request to client */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zsend_assign_label_chunk_response(struct zserv *client,
|
|
|
|
vrf_id_t vrf_id,
|
|
|
|
struct label_manager_chunk *lmc)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
s = client->obuf;
|
|
|
|
stream_reset(s);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zserv_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (lmc) {
|
|
|
|
/* keep */
|
|
|
|
stream_putc(s, lmc->keep);
|
|
|
|
/* start and end labels */
|
|
|
|
stream_putl(s, lmc->start);
|
|
|
|
stream_putl(s, lmc->end);
|
|
|
|
}
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Write packet size. */
|
|
|
|
stream_putw_at(s, 0, stream_get_endp(s));
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return writen(client->sock, s->data, stream_get_endp(s));
|
2017-03-20 15:34:49 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct stream *s;
|
|
|
|
u_char keep;
|
|
|
|
uint32_t size;
|
|
|
|
struct label_manager_chunk *lmc;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Get data. */
|
|
|
|
keep = stream_getc(s);
|
|
|
|
size = stream_getl(s);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
lmc = assign_label_chunk(client->proto, client->instance, keep, size);
|
|
|
|
if (!lmc)
|
|
|
|
zlog_err("%s: Unable to assign Label Chunk of size %u",
|
|
|
|
__func__, size);
|
|
|
|
else
|
|
|
|
zlog_debug("Assigned Label Chunk %u - %u to %u", lmc->start,
|
|
|
|
lmc->end, keep);
|
|
|
|
/* send response back */
|
|
|
|
zsend_assign_label_chunk_response(client, vrf_id, lmc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zread_release_label_chunk(struct zserv *client)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
uint32_t start, end;
|
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Get data. */
|
|
|
|
start = stream_getl(s);
|
|
|
|
end = stream_getl(s);
|
|
|
|
|
|
|
|
release_label_chunk(client->proto, client->instance, start, end);
|
|
|
|
}
|
|
|
|
static void zread_label_manager_request(int cmd, struct zserv *client,
|
2017-10-11 14:41:29 +02:00
|
|
|
struct zebra_vrf *zvrf)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
/* to avoid sending other messages like ZERBA_INTERFACE_UP */
|
|
|
|
if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
|
|
|
|
client->is_synchronous = 1;
|
|
|
|
|
|
|
|
/* external label manager */
|
|
|
|
if (lm_is_external)
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_relay_label_manager_request(cmd, client,
|
|
|
|
zvrf_id(zvrf));
|
2017-07-17 14:03:14 +02:00
|
|
|
/* this is a label manager */
|
|
|
|
else {
|
|
|
|
if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_label_manager_connect(client,
|
|
|
|
zvrf_id(zvrf));
|
2017-07-17 14:03:14 +02:00
|
|
|
else {
|
|
|
|
/* Sanity: don't allow 'unidentified' requests */
|
|
|
|
if (!client->proto) {
|
|
|
|
zlog_err(
|
|
|
|
"Got label request from an unidentified client");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cmd == ZEBRA_GET_LABEL_CHUNK)
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_get_label_chunk(client,
|
|
|
|
zvrf_id(zvrf));
|
2017-07-17 14:03:14 +02:00
|
|
|
else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
|
|
|
|
zread_release_label_chunk(client);
|
|
|
|
}
|
|
|
|
}
|
2017-03-20 15:34:49 +01:00
|
|
|
}
|
|
|
|
|
2017-05-15 17:09:28 +02:00
|
|
|
static int zread_pseudowire(int command, struct zserv *client, u_short length,
|
2017-10-11 14:41:29 +02:00
|
|
|
struct zebra_vrf *zvrf)
|
2017-05-15 17:09:28 +02:00
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
char ifname[IF_NAMESIZE];
|
|
|
|
ifindex_t ifindex;
|
|
|
|
int type;
|
|
|
|
int af;
|
|
|
|
union g_addr nexthop;
|
|
|
|
uint32_t local_label;
|
|
|
|
uint32_t remote_label;
|
|
|
|
uint8_t flags;
|
|
|
|
union pw_protocol_fields data;
|
|
|
|
uint8_t protocol;
|
|
|
|
struct zebra_pw *pw;
|
|
|
|
|
|
|
|
/* Get input stream. */
|
|
|
|
s = client->ibuf;
|
|
|
|
|
|
|
|
/* Get data. */
|
|
|
|
stream_get(ifname, s, IF_NAMESIZE);
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
type = stream_getl(s);
|
|
|
|
af = stream_getl(s);
|
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
|
|
|
nexthop.ipv4.s_addr = stream_get_ipv4(s);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
stream_get(&nexthop.ipv6, s, 16);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
local_label = stream_getl(s);
|
|
|
|
remote_label = stream_getl(s);
|
|
|
|
flags = stream_getc(s);
|
|
|
|
stream_get(&data, s, sizeof(data));
|
|
|
|
protocol = client->proto;
|
|
|
|
|
|
|
|
pw = zebra_pw_find(zvrf, ifname);
|
|
|
|
switch (command) {
|
|
|
|
case ZEBRA_PW_ADD:
|
|
|
|
if (pw) {
|
|
|
|
zlog_warn("%s: pseudowire %s already exists [%s]",
|
|
|
|
__func__, ifname,
|
|
|
|
zserv_command_string(command));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
zebra_pw_add(zvrf, ifname, protocol, client);
|
|
|
|
break;
|
|
|
|
case ZEBRA_PW_DELETE:
|
|
|
|
if (!pw) {
|
|
|
|
zlog_warn("%s: pseudowire %s not found [%s]", __func__,
|
|
|
|
ifname, zserv_command_string(command));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
zebra_pw_del(zvrf, pw);
|
|
|
|
break;
|
|
|
|
case ZEBRA_PW_SET:
|
|
|
|
case ZEBRA_PW_UNSET:
|
|
|
|
if (!pw) {
|
|
|
|
zlog_warn("%s: pseudowire %s not found [%s]", __func__,
|
|
|
|
ifname, zserv_command_string(command));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (command) {
|
|
|
|
case ZEBRA_PW_SET:
|
|
|
|
pw->enabled = 1;
|
|
|
|
break;
|
|
|
|
case ZEBRA_PW_UNSET:
|
|
|
|
pw->enabled = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label,
|
|
|
|
remote_label, flags, &data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
|
|
|
|
static void zebra_client_close_cleanup_rnh(struct zserv *client)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct vrf *vrf;
|
|
|
|
struct zebra_vrf *zvrf;
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-09-15 17:47:35 +02:00
|
|
|
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
|
2017-07-17 14:03:14 +02:00
|
|
|
if ((zvrf = vrf->info) != NULL) {
|
|
|
|
zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client,
|
|
|
|
RNH_NEXTHOP_TYPE);
|
|
|
|
zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6,
|
|
|
|
client, RNH_NEXTHOP_TYPE);
|
|
|
|
zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client,
|
|
|
|
RNH_IMPORT_CHECK_TYPE);
|
|
|
|
zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6,
|
|
|
|
client, RNH_IMPORT_CHECK_TYPE);
|
|
|
|
if (client->proto == ZEBRA_ROUTE_LDP) {
|
|
|
|
hash_iterate(zvrf->lsp_table,
|
|
|
|
mpls_ldp_lsp_uninstall_all,
|
|
|
|
zvrf->lsp_table);
|
|
|
|
mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP);
|
|
|
|
mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-20 15:34:49 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-09-20 18:52:38 +02:00
|
|
|
/* free zebra client information. */
|
|
|
|
static void zebra_client_free(struct zserv *client)
|
2017-03-20 15:34:49 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Send client de-registration to BFD */
|
|
|
|
zebra_ptm_bfd_client_deregister(client->proto);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Cleanup any registered nexthops - across all VRFs. */
|
|
|
|
zebra_client_close_cleanup_rnh(client);
|
2016-06-01 19:19:30 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Release Label Manager chunks */
|
|
|
|
release_daemon_chunks(client->proto, client->instance);
|
2016-03-02 02:08:43 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Cleanup any FECs registered by this client. */
|
|
|
|
zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
|
|
|
|
client);
|
|
|
|
|
2017-05-15 17:09:28 +02:00
|
|
|
/* Remove pseudowires associated with this client */
|
|
|
|
zebra_pw_client_close(client);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Close file descriptor. */
|
|
|
|
if (client->sock) {
|
|
|
|
unsigned long nroutes;
|
|
|
|
|
|
|
|
close(client->sock);
|
|
|
|
nroutes = rib_score_proto(client->proto, client->instance);
|
|
|
|
zlog_notice(
|
|
|
|
"client %d disconnected. %lu %s routes removed from the rib",
|
|
|
|
client->sock, nroutes,
|
|
|
|
zebra_route_string(client->proto));
|
|
|
|
client->sock = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free stream buffers. */
|
|
|
|
if (client->ibuf)
|
|
|
|
stream_free(client->ibuf);
|
|
|
|
if (client->obuf)
|
|
|
|
stream_free(client->obuf);
|
|
|
|
if (client->wb)
|
|
|
|
buffer_free(client->wb);
|
|
|
|
|
|
|
|
/* Release threads. */
|
|
|
|
if (client->t_read)
|
|
|
|
thread_cancel(client->t_read);
|
|
|
|
if (client->t_write)
|
|
|
|
thread_cancel(client->t_write);
|
|
|
|
if (client->t_suicide)
|
|
|
|
thread_cancel(client->t_suicide);
|
|
|
|
|
|
|
|
/* Free bitmaps. */
|
|
|
|
for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
|
|
|
|
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
|
|
|
vrf_bitmap_free(client->redist[afi][i]);
|
|
|
|
|
|
|
|
vrf_bitmap_free(client->redist_default);
|
|
|
|
vrf_bitmap_free(client->ifinfo);
|
|
|
|
vrf_bitmap_free(client->ridinfo);
|
|
|
|
|
|
|
|
XFREE(MTYPE_TMP, client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-09-20 18:52:38 +02:00
|
|
|
static void zebra_client_close(struct zserv *client)
|
|
|
|
{
|
|
|
|
listnode_delete(zebrad.client_list, client);
|
|
|
|
zebra_client_free(client);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Make new client. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_client_create(int sock)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct zserv *client;
|
|
|
|
int i;
|
|
|
|
afi_t afi;
|
|
|
|
|
|
|
|
client = XCALLOC(MTYPE_TMP, sizeof(struct zserv));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Make client input/output buffer. */
|
|
|
|
client->sock = sock;
|
|
|
|
client->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
|
|
|
client->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
|
|
|
client->wb = buffer_new(0);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set table number. */
|
|
|
|
client->rtm_table = zebrad.rtm_table_default;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
client->connect_time = monotime(NULL);
|
|
|
|
/* Initialize flags */
|
|
|
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
|
|
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
|
|
|
client->redist[afi][i] = vrf_bitmap_init();
|
|
|
|
client->redist_default = vrf_bitmap_init();
|
|
|
|
client->ifinfo = vrf_bitmap_init();
|
|
|
|
client->ridinfo = vrf_bitmap_init();
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* by default, it's not a synchronous client */
|
|
|
|
client->is_synchronous = 0;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Add this client to linked list. */
|
|
|
|
listnode_add(zebrad.client_list, client);
|
2017-03-20 15:34:49 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Make new read thread. */
|
|
|
|
zebra_event(ZEBRA_READ, sock, client);
|
2016-02-01 19:55:42 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
zebra_vrf_update_all(client);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-10-11 14:31:35 +02:00
|
|
|
static int zread_interface_set_master(struct zserv *client,
|
2017-06-13 14:59:32 +02:00
|
|
|
u_short length)
|
|
|
|
{
|
|
|
|
struct interface *master;
|
|
|
|
struct interface *slave;
|
|
|
|
struct stream *s = client->ibuf;
|
|
|
|
int ifindex;
|
|
|
|
vrf_id_t vrf_id;
|
|
|
|
|
|
|
|
vrf_id = stream_getw(s);
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
master = if_lookup_by_index(ifindex, vrf_id);
|
|
|
|
|
|
|
|
vrf_id = stream_getw(s);
|
|
|
|
ifindex = stream_getl(s);
|
|
|
|
slave = if_lookup_by_index(ifindex, vrf_id);
|
|
|
|
|
|
|
|
if (!master || !slave)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
kernel_interface_set_master(master, slave);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-10-11 14:58:02 +02:00
|
|
|
static inline void zserv_handle_commands(struct zserv *client,
|
|
|
|
uint16_t command,
|
|
|
|
uint16_t length,
|
|
|
|
struct zebra_vrf *zvrf)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
switch (command) {
|
|
|
|
case ZEBRA_ROUTER_ID_ADD:
|
|
|
|
zread_router_id_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_ROUTER_ID_DELETE:
|
|
|
|
zread_router_id_delete(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_INTERFACE_ADD:
|
|
|
|
zread_interface_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_INTERFACE_DELETE:
|
|
|
|
zread_interface_delete(client, length, zvrf);
|
|
|
|
break;
|
2017-08-20 02:59:41 +02:00
|
|
|
case ZEBRA_ROUTE_ADD:
|
|
|
|
zread_route_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_ROUTE_DELETE:
|
|
|
|
zread_route_del(client, length, zvrf);
|
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
case ZEBRA_IPV4_ROUTE_ADD:
|
|
|
|
zread_ipv4_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IPV4_ROUTE_DELETE:
|
|
|
|
zread_ipv4_delete(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
|
|
|
|
zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IPV6_ROUTE_ADD:
|
|
|
|
zread_ipv6_add(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IPV6_ROUTE_DELETE:
|
|
|
|
zread_ipv6_delete(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_REDISTRIBUTE_ADD:
|
|
|
|
zebra_redistribute_add(command, client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_REDISTRIBUTE_DELETE:
|
|
|
|
zebra_redistribute_delete(command, client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
|
|
|
|
zebra_redistribute_default_add(command, client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
|
|
|
|
zebra_redistribute_default_delete(command, client, length,
|
|
|
|
zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
|
|
|
|
zread_ipv4_nexthop_lookup_mrib(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_HELLO:
|
|
|
|
zread_hello(client);
|
|
|
|
break;
|
|
|
|
case ZEBRA_NEXTHOP_REGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_rnh_register(client, length, RNH_NEXTHOP_TYPE,
|
2017-07-17 14:03:14 +02:00
|
|
|
zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_NEXTHOP_UNREGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_rnh_unregister(client, length, RNH_NEXTHOP_TYPE,
|
2017-07-17 14:03:14 +02:00
|
|
|
zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IMPORT_ROUTE_REGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_rnh_register(client, length, RNH_IMPORT_CHECK_TYPE,
|
2017-07-17 14:03:14 +02:00
|
|
|
zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_IMPORT_ROUTE_UNREGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_rnh_unregister(client, length,
|
2017-07-17 14:03:14 +02:00
|
|
|
RNH_IMPORT_CHECK_TYPE, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_BFD_DEST_UPDATE:
|
|
|
|
case ZEBRA_BFD_DEST_REGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_ptm_bfd_dst_register(client, length, command, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_BFD_DEST_DEREGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_ptm_bfd_dst_deregister(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_VRF_UNREGISTER:
|
|
|
|
zread_vrf_unregister(client, length, zvrf);
|
|
|
|
break;
|
|
|
|
case ZEBRA_BFD_CLIENT_REGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_ptm_bfd_client_register(client, length);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_INTERFACE_ENABLE_RADV:
|
|
|
|
#if defined(HAVE_RTADV)
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_interface_radv_set(client, length, zvrf, 1);
|
2017-06-08 13:55:25 +02:00
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_INTERFACE_DISABLE_RADV:
|
|
|
|
#if defined(HAVE_RTADV)
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_interface_radv_set(client, length, zvrf, 0);
|
2017-06-08 13:55:25 +02:00
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_MPLS_LABELS_ADD:
|
|
|
|
case ZEBRA_MPLS_LABELS_DELETE:
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_mpls_labels(command, client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_IPMR_ROUTE_STATS:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_ipmr_route_stats(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_LABEL_MANAGER_CONNECT:
|
|
|
|
case ZEBRA_GET_LABEL_CHUNK:
|
|
|
|
case ZEBRA_RELEASE_LABEL_CHUNK:
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_label_manager_request(command, client, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_FEC_REGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_fec_register(client, length);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_FEC_UNREGISTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zserv_fec_unregister(client, length);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2017-06-28 10:51:10 +02:00
|
|
|
case ZEBRA_ADVERTISE_DEFAULT_GW:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_advertise_gw_macip(client, length, zvrf);
|
2017-06-28 10:51:10 +02:00
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
case ZEBRA_ADVERTISE_ALL_VNI:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_advertise_all_vni(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_REMOTE_VTEP_ADD:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_remote_vtep_add(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_REMOTE_VTEP_DEL:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_remote_vtep_del(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_REMOTE_MACIP_ADD:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_remote_macip_add(client, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_REMOTE_MACIP_DEL:
|
2017-10-11 14:31:35 +02:00
|
|
|
zebra_vxlan_remote_macip_del(client, length, zvrf);
|
2017-06-20 00:24:24 +02:00
|
|
|
break;
|
2017-06-13 14:59:32 +02:00
|
|
|
case ZEBRA_INTERFACE_SET_MASTER:
|
2017-10-11 14:31:35 +02:00
|
|
|
zread_interface_set_master(client, length);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2017-05-15 17:09:28 +02:00
|
|
|
case ZEBRA_PW_ADD:
|
|
|
|
case ZEBRA_PW_DELETE:
|
|
|
|
case ZEBRA_PW_SET:
|
|
|
|
case ZEBRA_PW_UNSET:
|
2017-10-11 14:41:29 +02:00
|
|
|
zread_pseudowire(command, client, length, zvrf);
|
2017-05-15 17:09:28 +02:00
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
default:
|
|
|
|
zlog_info("Zebra received unknown command %d", command);
|
|
|
|
break;
|
|
|
|
}
|
2017-10-11 14:58:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handler of zebra service request. */
|
|
|
|
static int zebra_client_read(struct thread *thread)
|
|
|
|
{
|
|
|
|
int sock;
|
|
|
|
struct zserv *client;
|
|
|
|
size_t already;
|
|
|
|
uint16_t length, command;
|
|
|
|
uint8_t marker, version;
|
|
|
|
vrf_id_t vrf_id;
|
|
|
|
struct zebra_vrf *zvrf;
|
|
|
|
|
|
|
|
/* Get thread data. Reset reading thread because I'm running. */
|
|
|
|
sock = THREAD_FD(thread);
|
|
|
|
client = THREAD_ARG(thread);
|
|
|
|
client->t_read = NULL;
|
|
|
|
|
|
|
|
if (client->t_suicide) {
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read length and command (if we don't have it already). */
|
|
|
|
if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) {
|
|
|
|
ssize_t nbyte;
|
|
|
|
if (((nbyte = stream_read_try(client->ibuf, sock,
|
|
|
|
ZEBRA_HEADER_SIZE - already))
|
|
|
|
== 0)
|
|
|
|
|| (nbyte == -1)) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug("connection closed socket [%d]",
|
|
|
|
sock);
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
|
|
|
|
/* Try again later. */
|
|
|
|
zebra_event(ZEBRA_READ, sock, client);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
already = ZEBRA_HEADER_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset to read from the beginning of the incoming packet. */
|
|
|
|
stream_set_getp(client->ibuf, 0);
|
|
|
|
|
|
|
|
/* Fetch header values */
|
|
|
|
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) {
|
|
|
|
zlog_err(
|
|
|
|
"%s: socket %d version mismatch, marker %d, version %d",
|
|
|
|
__func__, sock, marker, version);
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (length < ZEBRA_HEADER_SIZE) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: socket %d message length %u is less than header size %d",
|
|
|
|
__func__, sock, length, ZEBRA_HEADER_SIZE);
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (length > STREAM_SIZE(client->ibuf)) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: socket %d message length %u exceeds buffer size %lu",
|
|
|
|
__func__, sock, length,
|
|
|
|
(u_long)STREAM_SIZE(client->ibuf));
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read rest of data. */
|
|
|
|
if (already < length) {
|
|
|
|
ssize_t nbyte;
|
|
|
|
if (((nbyte = stream_read_try(client->ibuf, sock,
|
|
|
|
length - already))
|
|
|
|
== 0)
|
|
|
|
|| (nbyte == -1)) {
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"connection closed [%d] when reading zebra data",
|
|
|
|
sock);
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (nbyte != (ssize_t)(length - already)) {
|
|
|
|
/* Try again later. */
|
|
|
|
zebra_event(ZEBRA_READ, sock, client);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
length -= ZEBRA_HEADER_SIZE;
|
|
|
|
|
|
|
|
/* Debug packet information. */
|
|
|
|
if (IS_ZEBRA_DEBUG_EVENT)
|
|
|
|
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 in VRF %u",
|
|
|
|
zserv_command_string(command), length, vrf_id);
|
|
|
|
|
|
|
|
client->last_read_time = monotime(NULL);
|
|
|
|
client->last_read_cmd = command;
|
|
|
|
|
|
|
|
zvrf = zebra_vrf_lookup_by_id(vrf_id);
|
|
|
|
if (!zvrf) {
|
|
|
|
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
|
|
|
|
zlog_debug("zebra received unknown VRF[%u]", vrf_id);
|
|
|
|
goto zclient_read_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
zserv_handle_commands(client, command, length, zvrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (client->t_suicide) {
|
|
|
|
/* No need to wait for thread callback, just kill immediately.
|
|
|
|
*/
|
|
|
|
zebra_client_close(client);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
zclient_read_out:
|
|
|
|
stream_reset(client->ibuf);
|
|
|
|
zebra_event(ZEBRA_READ, sock, client);
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Accept code of zebra server socket. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int zebra_accept(struct thread *thread)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int accept_sock;
|
|
|
|
int client_sock;
|
|
|
|
struct sockaddr_in client;
|
|
|
|
socklen_t len;
|
|
|
|
|
|
|
|
accept_sock = THREAD_FD(thread);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Reregister myself. */
|
|
|
|
zebra_event(ZEBRA_SERV, accept_sock, NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
len = sizeof(struct sockaddr_in);
|
|
|
|
client_sock = accept(accept_sock, (struct sockaddr *)&client, &len);
|
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
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (client_sock < 0) {
|
|
|
|
zlog_warn("Can't accept zebra socket: %s",
|
|
|
|
safe_strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Make client socket non-blocking. */
|
|
|
|
set_nonblocking(client_sock);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Create new zebra client. */
|
|
|
|
zebra_client_create(client_sock);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-06 07:35:50 +02:00
|
|
|
/* Make zebra server socket, wiping any existing one (see bug #403). */
|
|
|
|
void zebra_zserv_socket_init(char *path)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
int ret;
|
2017-08-06 07:35:50 +02:00
|
|
|
int sock;
|
2017-07-17 14:03:14 +02:00
|
|
|
mode_t old_mask;
|
2017-08-06 07:35:50 +02:00
|
|
|
struct sockaddr_storage sa;
|
|
|
|
socklen_t sa_len;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-06 07:35:50 +02:00
|
|
|
if (!frr_zclient_addr(&sa, &sa_len, path))
|
|
|
|
/* should be caught in zebra main() */
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Set umask */
|
|
|
|
old_mask = umask(0077);
|
|
|
|
|
|
|
|
/* Make UNIX domain socket. */
|
2017-08-06 07:35:50 +02:00
|
|
|
sock = socket(sa.ss_family, SOCK_STREAM, 0);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (sock < 0) {
|
2017-08-06 07:35:50 +02:00
|
|
|
zlog_warn("Can't create zserv socket: %s",
|
2017-07-17 14:03:14 +02:00
|
|
|
safe_strerror(errno));
|
|
|
|
zlog_warn(
|
|
|
|
"zebra can't provide full functionality due to above error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-06 07:35:50 +02:00
|
|
|
if (sa.ss_family != AF_UNIX) {
|
|
|
|
sockopt_reuseaddr(sock);
|
|
|
|
sockopt_reuseport(sock);
|
|
|
|
} else {
|
|
|
|
struct sockaddr_un *suna = (struct sockaddr_un *)&sa;
|
|
|
|
if (suna->sun_path[0])
|
|
|
|
unlink(suna->sun_path);
|
|
|
|
}
|
|
|
|
|
2017-10-11 15:16:46 +02:00
|
|
|
zserv_privs.change(ZPRIVS_RAISE);
|
|
|
|
setsockopt_so_recvbuf(sock, 1048576);
|
|
|
|
setsockopt_so_sendbuf(sock, 1048576);
|
|
|
|
zserv_privs.change(ZPRIVS_LOWER);
|
|
|
|
|
2017-08-12 21:02:42 +02:00
|
|
|
if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_RAISE))
|
2017-08-06 07:35:50 +02:00
|
|
|
zlog_err("Can't raise privileges");
|
|
|
|
|
|
|
|
ret = bind(sock, (struct sockaddr *)&sa, sa_len);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret < 0) {
|
2017-08-06 07:35:50 +02:00
|
|
|
zlog_warn("Can't bind zserv socket on %s: %s", path,
|
2017-07-17 14:03:14 +02:00
|
|
|
safe_strerror(errno));
|
|
|
|
zlog_warn(
|
|
|
|
"zebra can't provide full functionality due to above error");
|
|
|
|
close(sock);
|
|
|
|
return;
|
|
|
|
}
|
2017-08-12 21:02:42 +02:00
|
|
|
if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_LOWER))
|
2017-08-06 07:35:50 +02:00
|
|
|
zlog_err("Can't lower privileges");
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
ret = listen(sock, 5);
|
|
|
|
if (ret < 0) {
|
2017-08-06 07:35:50 +02:00
|
|
|
zlog_warn("Can't listen to zserv socket %s: %s", path,
|
2017-07-17 14:03:14 +02:00
|
|
|
safe_strerror(errno));
|
|
|
|
zlog_warn(
|
|
|
|
"zebra can't provide full functionality due to above error");
|
|
|
|
close(sock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
umask(old_mask);
|
|
|
|
|
|
|
|
zebra_event(ZEBRA_SERV, sock, NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void zebra_event(enum event event, int sock, struct zserv *client)
|
|
|
|
{
|
|
|
|
switch (event) {
|
|
|
|
case ZEBRA_SERV:
|
|
|
|
thread_add_read(zebrad.master, zebra_accept, client, sock,
|
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
case ZEBRA_READ:
|
|
|
|
client->t_read = NULL;
|
|
|
|
thread_add_read(zebrad.master, zebra_client_read, client, sock,
|
|
|
|
&client->t_read);
|
|
|
|
break;
|
|
|
|
case ZEBRA_WRITE:
|
|
|
|
/**/
|
|
|
|
break;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2015-05-20 02:47:22 +02:00
|
|
|
#define ZEBRA_TIME_BUF 32
|
2017-07-17 14:03:14 +02:00
|
|
|
static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
|
2015-05-20 02:47:22 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct tm *tm;
|
|
|
|
time_t now;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
assert(buf != NULL);
|
|
|
|
assert(buflen >= ZEBRA_TIME_BUF);
|
|
|
|
assert(time1 != NULL);
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!*time1) {
|
|
|
|
snprintf(buf, buflen, "never ");
|
|
|
|
return (buf);
|
|
|
|
}
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
now = monotime(NULL);
|
|
|
|
now -= *time1;
|
|
|
|
tm = gmtime(&now);
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (now < ONE_DAY_SECOND)
|
|
|
|
snprintf(buf, buflen, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
|
|
|
|
tm->tm_sec);
|
|
|
|
else if (now < ONE_WEEK_SECOND)
|
|
|
|
snprintf(buf, buflen, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
|
|
|
|
tm->tm_min);
|
2017-06-21 05:10:57 +02:00
|
|
|
else
|
2017-07-17 14:03:14 +02:00
|
|
|
snprintf(buf, buflen, "%02dw%dd%02dh", tm->tm_yday / 7,
|
|
|
|
tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
|
|
|
{
|
|
|
|
char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
|
|
|
|
char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
|
|
|
|
|
|
|
|
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
|
|
|
|
if (client->instance)
|
|
|
|
vty_out(vty, " Instance: %d", client->instance);
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
vty_out(vty, "------------------------ \n");
|
|
|
|
vty_out(vty, "FD: %d \n", client->sock);
|
|
|
|
vty_out(vty, "Route Table ID: %d \n", client->rtm_table);
|
|
|
|
|
|
|
|
vty_out(vty, "Connect Time: %s \n",
|
|
|
|
zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF));
|
|
|
|
if (client->nh_reg_time) {
|
|
|
|
vty_out(vty, "Nexthop Registry Time: %s \n",
|
|
|
|
zserv_time_buf(&client->nh_reg_time, nhbuf,
|
|
|
|
ZEBRA_TIME_BUF));
|
|
|
|
if (client->nh_last_upd_time)
|
|
|
|
vty_out(vty, "Nexthop Last Update Time: %s \n",
|
|
|
|
zserv_time_buf(&client->nh_last_upd_time, mbuf,
|
|
|
|
ZEBRA_TIME_BUF));
|
|
|
|
else
|
|
|
|
vty_out(vty, "No Nexthop Update sent\n");
|
|
|
|
} else
|
|
|
|
vty_out(vty, "Not registered for Nexthop Updates\n");
|
|
|
|
|
|
|
|
vty_out(vty, "Last Msg Rx Time: %s \n",
|
|
|
|
zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF));
|
|
|
|
vty_out(vty, "Last Msg Tx Time: %s \n",
|
|
|
|
zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF));
|
|
|
|
if (client->last_read_time)
|
|
|
|
vty_out(vty, "Last Rcvd Cmd: %s \n",
|
|
|
|
zserv_command_string(client->last_read_cmd));
|
|
|
|
if (client->last_write_time)
|
|
|
|
vty_out(vty, "Last Sent Cmd: %s \n",
|
|
|
|
zserv_command_string(client->last_write_cmd));
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
|
|
|
|
vty_out(vty, "Type Add Update Del \n");
|
|
|
|
vty_out(vty, "================================================== \n");
|
|
|
|
vty_out(vty, "IPv4 %-12d%-12d%-12d\n", client->v4_route_add_cnt,
|
|
|
|
client->v4_route_upd8_cnt, client->v4_route_del_cnt);
|
|
|
|
vty_out(vty, "IPv6 %-12d%-12d%-12d\n", client->v6_route_add_cnt,
|
|
|
|
client->v6_route_upd8_cnt, client->v6_route_del_cnt);
|
|
|
|
vty_out(vty, "Redist:v4 %-12d%-12d%-12d\n", client->redist_v4_add_cnt,
|
|
|
|
0, client->redist_v4_del_cnt);
|
|
|
|
vty_out(vty, "Redist:v6 %-12d%-12d%-12d\n", client->redist_v6_add_cnt,
|
|
|
|
0, client->redist_v6_del_cnt);
|
|
|
|
vty_out(vty, "Connected %-12d%-12d%-12d\n", client->ifadd_cnt, 0,
|
|
|
|
client->ifdel_cnt);
|
|
|
|
vty_out(vty, "BFD peer %-12d%-12d%-12d\n", client->bfd_peer_add_cnt,
|
|
|
|
client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt);
|
|
|
|
vty_out(vty, "Interface Up Notifications: %d\n", client->ifup_cnt);
|
|
|
|
vty_out(vty, "Interface Down Notifications: %d\n", client->ifdown_cnt);
|
|
|
|
vty_out(vty, "VNI add notifications: %d\n", client->vniadd_cnt);
|
|
|
|
vty_out(vty, "VNI delete notifications: %d\n", client->vnidel_cnt);
|
|
|
|
vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
|
|
|
|
vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
|
|
|
|
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
|
|
|
|
{
|
|
|
|
char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
|
|
|
|
char wbuf[ZEBRA_TIME_BUF];
|
|
|
|
|
|
|
|
vty_out(vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d\n",
|
|
|
|
zebra_route_string(client->proto),
|
|
|
|
zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF),
|
|
|
|
zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF),
|
|
|
|
zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF),
|
|
|
|
client->v4_route_add_cnt + client->v4_route_upd8_cnt,
|
|
|
|
client->v4_route_del_cnt,
|
|
|
|
client->v6_route_add_cnt + client->v6_route_upd8_cnt,
|
|
|
|
client->v6_route_del_cnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct zserv *zebra_find_client(u_char proto)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct zserv *client;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
|
|
|
|
if (client->proto == proto)
|
|
|
|
return client;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2016-07-21 17:50:17 +02:00
|
|
|
}
|
|
|
|
|
2017-01-18 16:17:20 +01:00
|
|
|
#ifdef HAVE_NETLINK
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Display default rtm_table for all clients. */
|
|
|
|
DEFUN (show_table,
|
|
|
|
show_table_cmd,
|
|
|
|
"show table",
|
|
|
|
SHOW_STR
|
|
|
|
"default routing table to use for all clients\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty, "table %d\n", zebrad.rtm_table_default);
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-23 15:47:20 +02:00
|
|
|
DEFUN (config_table,
|
2002-12-13 21:15:29 +01:00
|
|
|
config_table_cmd,
|
|
|
|
"table TABLENO",
|
|
|
|
"Configure target kernel routing table\n"
|
|
|
|
"TABLE integer\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2015-11-23 19:05:03 +01:00
|
|
|
DEFUN (no_config_table,
|
|
|
|
no_config_table_cmd,
|
2016-09-24 23:58:50 +02:00
|
|
|
"no table [TABLENO]",
|
2015-11-23 19:05:03 +01:00
|
|
|
NO_STR
|
|
|
|
"Configure target kernel routing table\n"
|
|
|
|
"TABLE integer\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
zebrad.rtm_table_default = 0;
|
|
|
|
return CMD_SUCCESS;
|
2015-11-23 19:05:03 +01:00
|
|
|
}
|
2017-01-18 16:17:20 +01:00
|
|
|
#endif
|
2015-11-23 19:05:03 +01:00
|
|
|
|
2003-05-25 13:43:52 +02:00
|
|
|
DEFUN (ip_forwarding,
|
|
|
|
ip_forwarding_cmd,
|
|
|
|
"ip forwarding",
|
|
|
|
IP_STR
|
|
|
|
"Turn on IP forwarding")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2003-05-25 13:43:52 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward();
|
|
|
|
if (ret == 0)
|
|
|
|
ret = ipforward_on();
|
2003-05-25 13:43:52 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
vty_out(vty, "Can't turn on IP forwarding\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2003-05-25 13:43:52 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2003-05-25 13:43:52 +02:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_ip_forwarding,
|
|
|
|
no_ip_forwarding_cmd,
|
|
|
|
"no ip forwarding",
|
|
|
|
NO_STR
|
|
|
|
IP_STR
|
|
|
|
"Turn off IP forwarding")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward();
|
|
|
|
if (ret != 0)
|
|
|
|
ret = ipforward_off();
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret != 0) {
|
|
|
|
vty_out(vty, "Can't turn off IP forwarding\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-05-18 19:13:32 +02:00
|
|
|
DEFUN (show_zebra,
|
|
|
|
show_zebra_cmd,
|
|
|
|
"show zebra",
|
|
|
|
SHOW_STR
|
|
|
|
"Zebra information\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct vrf *vrf;
|
2017-05-18 19:13:32 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty,
|
|
|
|
" Route Route Neighbor LSP LSP\n");
|
|
|
|
vty_out(vty,
|
|
|
|
"VRF Installs Removals Updates Installs Removals\n");
|
2017-09-15 17:47:35 +02:00
|
|
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
2017-07-17 14:03:14 +02:00
|
|
|
struct zebra_vrf *zvrf = vrf->info;
|
2017-07-22 14:52:33 +02:00
|
|
|
vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
|
|
|
|
" %10" PRIu64 " %10" PRIu64 "\n",
|
2017-07-17 14:03:14 +02:00
|
|
|
vrf->name, zvrf->installs, zvrf->removals,
|
|
|
|
zvrf->neigh_updates, zvrf->lsp_installs,
|
|
|
|
zvrf->lsp_removals);
|
|
|
|
}
|
2017-05-18 19:13:32 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2017-05-18 19:13:32 +02:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* This command is for debugging purpose. */
|
|
|
|
DEFUN (show_zebra_client,
|
|
|
|
show_zebra_client_cmd,
|
|
|
|
"show zebra client",
|
|
|
|
SHOW_STR
|
2016-10-06 01:02:57 +02:00
|
|
|
"Zebra information\n"
|
2017-01-30 01:07:04 +01:00
|
|
|
"Client information\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct listnode *node;
|
|
|
|
struct zserv *client;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
|
|
|
|
zebra_show_client_detail(vty, client);
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2015-05-20 02:47:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This command is for debugging purpose. */
|
|
|
|
DEFUN (show_zebra_client_summary,
|
|
|
|
show_zebra_client_summary_cmd,
|
|
|
|
"show zebra client summary",
|
|
|
|
SHOW_STR
|
2017-01-30 01:07:04 +01:00
|
|
|
"Zebra information brief\n"
|
|
|
|
"Client information brief\n"
|
|
|
|
"Brief Summary\n")
|
2015-05-20 02:47:22 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct listnode *node;
|
|
|
|
struct zserv *client;
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty,
|
|
|
|
"Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes \n");
|
|
|
|
vty_out(vty,
|
|
|
|
"--------------------------------------------------------------------------------\n");
|
2015-05-20 02:47:22 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
|
|
|
|
zebra_show_client_brief(vty, client);
|
2015-05-20 02:40:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty, "Routes column shows (added+updated)/deleted\n");
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Table configuration write function. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int config_write_table(struct vty *vty)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if (zebrad.rtm_table_default)
|
|
|
|
vty_out(vty, "table %d\n", zebrad.rtm_table_default);
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* table node for routing tables. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static struct cmd_node table_node = {TABLE_NODE,
|
|
|
|
"", /* This node has no interface. */
|
|
|
|
1};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Only display ip forwarding is enabled or not. */
|
|
|
|
DEFUN (show_ip_forwarding,
|
|
|
|
show_ip_forwarding_cmd,
|
|
|
|
"show ip forwarding",
|
|
|
|
SHOW_STR
|
|
|
|
IP_STR
|
|
|
|
"IP forwarding status\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward();
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0)
|
|
|
|
vty_out(vty, "IP forwarding is off\n");
|
|
|
|
else
|
|
|
|
vty_out(vty, "IP forwarding is on\n");
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Only display ipv6 forwarding is enabled or not. */
|
|
|
|
DEFUN (show_ipv6_forwarding,
|
|
|
|
show_ipv6_forwarding_cmd,
|
|
|
|
"show ipv6 forwarding",
|
|
|
|
SHOW_STR
|
|
|
|
"IPv6 information\n"
|
|
|
|
"Forwarding status\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward_ipv6();
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
switch (ret) {
|
|
|
|
case -1:
|
|
|
|
vty_out(vty, "ipv6 forwarding is unknown\n");
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
vty_out(vty, "ipv6 forwarding is %s\n", "off");
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
vty_out(vty, "ipv6 forwarding is %s\n", "on");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vty_out(vty, "ipv6 forwarding is %s\n", "off");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-02-11 23:42:16 +01:00
|
|
|
DEFUN (ipv6_forwarding,
|
|
|
|
ipv6_forwarding_cmd,
|
|
|
|
"ipv6 forwarding",
|
|
|
|
IPV6_STR
|
|
|
|
"Turn on IPv6 forwarding")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2004-02-11 23:42:16 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward_ipv6();
|
|
|
|
if (ret == 0)
|
|
|
|
ret = ipforward_ipv6_on();
|
2004-04-06 13:59:00 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
vty_out(vty, "Can't turn on IPv6 forwarding\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2004-02-11 23:42:16 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2004-02-11 23:42:16 +01:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_ipv6_forwarding,
|
|
|
|
no_ipv6_forwarding_cmd,
|
|
|
|
"no ipv6 forwarding",
|
|
|
|
NO_STR
|
2004-02-11 23:42:16 +01:00
|
|
|
IPV6_STR
|
|
|
|
"Turn off IPv6 forwarding")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = ipforward_ipv6();
|
|
|
|
if (ret != 0)
|
|
|
|
ret = ipforward_ipv6_off();
|
2004-04-06 13:59:00 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret != 0) {
|
|
|
|
vty_out(vty, "Can't turn off IPv6 forwarding\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* IPForwarding configuration write function. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int config_write_forwarding(struct vty *vty)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
/* FIXME: Find better place for that. */
|
|
|
|
router_id_write(vty);
|
2004-10-03 20:18:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!ipforward())
|
|
|
|
vty_out(vty, "no ip forwarding\n");
|
|
|
|
if (!ipforward_ipv6())
|
|
|
|
vty_out(vty, "no ipv6 forwarding\n");
|
|
|
|
vty_out(vty, "!\n");
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* table node for routing tables. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static struct cmd_node forwarding_node = {FORWARDING_NODE,
|
|
|
|
"", /* This node has no interface. */
|
|
|
|
1};
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Initialisation of zebra and installation of commands. */
|
2017-07-17 14:03:14 +02:00
|
|
|
void zebra_init(void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Client list init. */
|
|
|
|
zebrad.client_list = list_new();
|
2017-09-20 18:52:38 +02:00
|
|
|
zebrad.client_list->del = (void (*)(void *))zebra_client_free;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Install configuration write function. */
|
|
|
|
install_node(&table_node, config_write_table);
|
|
|
|
install_node(&forwarding_node, config_write_forwarding);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(VIEW_NODE, &show_ip_forwarding_cmd);
|
|
|
|
install_element(CONFIG_NODE, &ip_forwarding_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
|
|
|
|
install_element(ENABLE_NODE, &show_zebra_cmd);
|
|
|
|
install_element(ENABLE_NODE, &show_zebra_client_cmd);
|
|
|
|
install_element(ENABLE_NODE, &show_zebra_client_summary_cmd);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_NETLINK
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(VIEW_NODE, &show_table_cmd);
|
|
|
|
install_element(CONFIG_NODE, &config_table_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_config_table_cmd);
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* HAVE_NETLINK */
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
|
|
|
|
install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
|
2007-05-02 18:05:35 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Route-map */
|
|
|
|
zebra_route_map_init();
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|