2003-12-23 09:09:43 +01:00
|
|
|
/*
|
|
|
|
* IS-IS Rout(e)ing protocol - isis_zebra.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
|
|
* Tampere University of Technology
|
|
|
|
* Institute of Communications Engineering
|
2015-11-12 14:24:22 +01:00
|
|
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
2003-12-23 09:09:43 +01:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public Licenseas published by the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program 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
|
2003-12-23 09:09:43 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "log.h"
|
2019-08-06 22:43:46 +02:00
|
|
|
#include "lib_errors.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "if.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "zclient.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "linklist.h"
|
2015-11-12 14:24:22 +01:00
|
|
|
#include "nexthop.h"
|
*: 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
|
|
|
#include "vrf.h"
|
2017-09-12 04:05:16 +02:00
|
|
|
#include "libfrr.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
#include "isisd/isis_constants.h"
|
|
|
|
#include "isisd/isis_common.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isisd/isis_flags.h"
|
|
|
|
#include "isisd/isis_misc.h"
|
|
|
|
#include "isisd/isis_circuit.h"
|
2005-09-04 23:36:36 +02:00
|
|
|
#include "isisd/isisd.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "isisd/isis_circuit.h"
|
|
|
|
#include "isisd/isis_csm.h"
|
2012-03-24 16:35:20 +01:00
|
|
|
#include "isisd/isis_lsp.h"
|
2020-11-26 03:39:09 +01:00
|
|
|
#include "isisd/isis_spf.h"
|
|
|
|
#include "isisd/isis_spf_private.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
#include "isisd/isis_route.h"
|
|
|
|
#include "isisd/isis_zebra.h"
|
2020-05-04 18:26:21 +02:00
|
|
|
#include "isisd/isis_adjacency.h"
|
2016-04-19 19:03:05 +02:00
|
|
|
#include "isisd/isis_te.h"
|
2019-08-04 03:02:37 +02:00
|
|
|
#include "isisd/isis_sr.h"
|
2020-07-22 20:32:35 +02:00
|
|
|
#include "isisd/isis_ldp_sync.h"
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2019-08-04 03:02:37 +02:00
|
|
|
struct zclient *zclient;
|
|
|
|
static struct zclient *zclient_sync;
|
|
|
|
|
2004-10-03 20:18:34 +02:00
|
|
|
/* Router-id update message from zebra. */
|
2019-05-03 21:42:59 +02:00
|
|
|
static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
|
2004-10-03 20:18:34 +02:00
|
|
|
{
|
2012-03-24 16:35:20 +01:00
|
|
|
struct isis_area *area;
|
|
|
|
struct listnode *node;
|
2004-10-03 20:18:34 +02:00
|
|
|
struct prefix router_id;
|
2020-07-13 14:37:59 +02:00
|
|
|
struct isis *isis = NULL;
|
|
|
|
|
|
|
|
isis = isis_lookup_by_vrfid(vrf_id);
|
|
|
|
|
|
|
|
if (isis == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
zebra_router_id_update_read(zclient->ibuf, &router_id);
|
|
|
|
if (isis->router_id == router_id.u.prefix4.s_addr)
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-03-24 16:35:20 +01:00
|
|
|
isis->router_id = router_id.u.prefix4.s_addr;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
|
|
|
|
if (listcount(area->area_addrs) > 0)
|
|
|
|
lsp_regenerate_schedule(area, area->is_type, 0);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-10-03 20:18:34 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2020-10-08 19:05:08 +02:00
|
|
|
struct isis_circuit *circuit;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct connected *c;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
|
*: 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
|
|
|
zclient->ibuf, vrf_id);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (c == NULL)
|
|
|
|
return 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2020-10-08 19:06:27 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2020-10-24 15:55:27 +02:00
|
|
|
if (c->address->family == AF_INET)
|
2020-10-18 13:33:54 +02:00
|
|
|
zlog_debug("connected IP address %pFX", c->address);
|
2020-10-24 15:55:27 +02:00
|
|
|
if (c->address->family == AF_INET6)
|
2020-10-18 13:33:54 +02:00
|
|
|
zlog_debug("connected IPv6 address %pFX", c->address);
|
2003-12-23 09:09:43 +01:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2020-10-08 19:05:08 +02:00
|
|
|
|
|
|
|
if (if_is_operative(c->ifp)) {
|
|
|
|
circuit = circuit_scan_by_ifp(c->ifp);
|
|
|
|
if (circuit)
|
|
|
|
isis_circuit_add_addr(circuit, c);
|
|
|
|
}
|
2003-12-23 09:09:43 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2020-10-08 19:05:08 +02:00
|
|
|
struct isis_circuit *circuit;
|
2003-12-23 09:09:43 +01:00
|
|
|
struct connected *c;
|
|
|
|
|
2004-09-10 22:48:21 +02:00
|
|
|
c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
|
*: 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
|
|
|
zclient->ibuf, vrf_id);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
if (c == NULL)
|
|
|
|
return 0;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2004-09-14 15:54:30 +02:00
|
|
|
#ifdef EXTREME_DEBUG
|
2020-10-24 15:55:27 +02:00
|
|
|
if (c->address->family == AF_INET)
|
2020-10-18 13:33:54 +02:00
|
|
|
zlog_debug("disconnected IP address %pFX", c->address);
|
2020-10-24 15:55:27 +02:00
|
|
|
if (c->address->family == AF_INET6)
|
2020-10-18 13:33:54 +02:00
|
|
|
zlog_debug("disconnected IPv6 address %pFX", c->address);
|
2004-09-14 15:54:30 +02:00
|
|
|
#endif /* EXTREME_DEBUG */
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2020-10-08 19:05:08 +02:00
|
|
|
if (if_is_operative(c->ifp)) {
|
|
|
|
circuit = circuit_scan_by_ifp(c->ifp);
|
|
|
|
if (circuit)
|
|
|
|
isis_circuit_del_addr(circuit, c);
|
|
|
|
}
|
|
|
|
|
2019-10-30 01:16:28 +01:00
|
|
|
connected_free(&c);
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
|
2016-04-19 19:03:05 +02:00
|
|
|
{
|
|
|
|
struct interface *ifp;
|
|
|
|
|
2019-01-18 19:06:00 +01:00
|
|
|
ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id);
|
2016-04-19 19:03:05 +02:00
|
|
|
|
|
|
|
if (ifp == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Update TE TLV */
|
|
|
|
isis_mpls_te_update(ifp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-21 00:55:42 +02:00
|
|
|
enum isis_zebra_nexthop_type {
|
2020-09-20 07:39:28 +02:00
|
|
|
ISIS_NEXTHOP_MAIN = 0,
|
|
|
|
ISIS_NEXTHOP_BACKUP,
|
2020-08-21 00:55:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops,
|
|
|
|
struct zapi_nexthop zapi_nexthops[],
|
|
|
|
enum isis_zebra_nexthop_type type,
|
2020-09-20 07:39:28 +02:00
|
|
|
bool mpls_lsp, uint8_t backup_nhs)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
|
|
|
struct isis_nexthop *nexthop;
|
|
|
|
struct listnode *node;
|
2017-08-21 02:18:36 +02:00
|
|
|
int count = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 02:29:35 +02:00
|
|
|
/* Nexthops */
|
2020-08-21 00:55:42 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(nexthops, node, nexthop)) {
|
|
|
|
struct zapi_nexthop *api_nh;
|
|
|
|
|
2019-08-06 22:43:46 +02:00
|
|
|
if (count >= MULTIPATH_NUM)
|
|
|
|
break;
|
2020-08-21 00:55:42 +02:00
|
|
|
api_nh = &zapi_nexthops[count];
|
2019-08-06 22:43:46 +02:00
|
|
|
if (fabricd)
|
2019-11-13 22:06:06 +01:00
|
|
|
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
|
2020-06-19 20:46:12 +02:00
|
|
|
api_nh->vrf_id = isis->vrf_id;
|
2019-08-06 22:43:46 +02:00
|
|
|
|
|
|
|
switch (nexthop->family) {
|
|
|
|
case AF_INET:
|
2017-08-21 02:29:35 +02:00
|
|
|
/* FIXME: can it be ? */
|
2019-08-06 22:43:46 +02:00
|
|
|
if (nexthop->ip.ipv4.s_addr != INADDR_ANY) {
|
2017-08-21 02:29:35 +02:00
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
2019-08-06 22:43:46 +02:00
|
|
|
api_nh->gate.ipv4 = nexthop->ip.ipv4;
|
2017-08-21 02:29:35 +02:00
|
|
|
} else {
|
|
|
|
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
|
|
|
|
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
|
2017-08-21 02:29:35 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
api_nh->gate.ipv6 = nexthop->ip.ipv6;
|
2017-08-21 02:29:35 +02:00
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
2019-08-06 22:43:46 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
|
|
"%s: unknown address family [%d]", __func__,
|
|
|
|
nexthop->family);
|
|
|
|
exit(1);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
|
|
|
|
api_nh->ifindex = nexthop->ifindex;
|
2020-08-21 00:55:42 +02:00
|
|
|
|
|
|
|
/* Add MPLS label(s). */
|
2020-11-20 04:54:41 +01:00
|
|
|
if (nexthop->label_stack) {
|
|
|
|
api_nh->label_num = nexthop->label_stack->num_labels;
|
|
|
|
memcpy(api_nh->labels, nexthop->label_stack->label,
|
|
|
|
sizeof(mpls_label_t) * api_nh->label_num);
|
|
|
|
} else if (nexthop->sr.present) {
|
|
|
|
api_nh->label_num = 1;
|
|
|
|
api_nh->labels[0] = nexthop->sr.label;
|
|
|
|
} else if (mpls_lsp) {
|
|
|
|
switch (type) {
|
|
|
|
case ISIS_NEXTHOP_MAIN:
|
2020-09-20 07:39:28 +02:00
|
|
|
/*
|
|
|
|
* Do not use non-SR enabled nexthops to prevent
|
|
|
|
* broken LSPs from being formed.
|
|
|
|
*/
|
|
|
|
continue;
|
2020-11-20 04:54:41 +01:00
|
|
|
case ISIS_NEXTHOP_BACKUP:
|
2020-09-20 07:39:28 +02:00
|
|
|
/*
|
|
|
|
* This is necessary because zebra requires
|
|
|
|
* the nexthops of MPLS LSPs to be labeled.
|
|
|
|
*/
|
2020-08-21 00:55:42 +02:00
|
|
|
api_nh->label_num = 1;
|
|
|
|
api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
|
2020-11-20 04:54:41 +01:00
|
|
|
break;
|
2020-08-21 00:55:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Backup nexthop handling. */
|
|
|
|
if (backup_nhs) {
|
|
|
|
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
|
|
|
|
/*
|
|
|
|
* If the backup has multiple nexthops, all of them
|
|
|
|
* protect the same primary nexthop since ECMP routes
|
|
|
|
* have no backups.
|
|
|
|
*/
|
|
|
|
api_nh->backup_num = backup_nhs;
|
|
|
|
for (int i = 0; i < backup_nhs; i++)
|
|
|
|
api_nh->backup_idx[i] = i;
|
|
|
|
}
|
2019-08-06 22:43:46 +02:00
|
|
|
count++;
|
2004-09-10 22:48:21 +02:00
|
|
|
}
|
2020-08-21 00:55:42 +02:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix,
|
|
|
|
struct prefix_ipv6 *src_p,
|
|
|
|
struct isis_route_info *route_info)
|
|
|
|
{
|
|
|
|
struct zapi_route api;
|
|
|
|
int count = 0;
|
|
|
|
|
2020-11-05 13:40:26 +01:00
|
|
|
if (zclient->sock < 0)
|
2017-08-21 02:18:36 +02:00
|
|
|
return;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2020-11-05 13:40:26 +01:00
|
|
|
/* Uninstall the route if it doesn't have any valid nexthop. */
|
|
|
|
if (list_isempty(route_info->nexthops)) {
|
|
|
|
isis_zebra_route_del_route(isis, prefix, src_p, route_info);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-21 00:55:42 +02:00
|
|
|
memset(&api, 0, sizeof(api));
|
|
|
|
api.vrf_id = isis->vrf_id;
|
|
|
|
api.type = PROTO_TYPE;
|
|
|
|
api.safi = SAFI_UNICAST;
|
|
|
|
api.prefix = *prefix;
|
|
|
|
if (src_p && src_p->prefixlen) {
|
|
|
|
api.src_prefix = *src_p;
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
|
|
|
|
}
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
|
|
|
api.metric = route_info->cost;
|
|
|
|
|
|
|
|
/* Add backup nexthops first. */
|
|
|
|
if (route_info->backup) {
|
|
|
|
count = isis_zebra_add_nexthops(
|
|
|
|
isis, route_info->backup->nexthops, api.backup_nexthops,
|
2020-09-20 07:39:28 +02:00
|
|
|
ISIS_NEXTHOP_BACKUP, false, 0);
|
2020-08-21 00:55:42 +02:00
|
|
|
if (count > 0) {
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
|
|
|
|
api.backup_nexthop_num = count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add primary nexthops. */
|
|
|
|
count = isis_zebra_add_nexthops(isis, route_info->nexthops,
|
2020-09-20 07:39:28 +02:00
|
|
|
api.nexthops, ISIS_NEXTHOP_MAIN, false,
|
2020-08-21 00:55:42 +02:00
|
|
|
count);
|
|
|
|
if (!count)
|
|
|
|
return;
|
2017-08-21 02:18:36 +02:00
|
|
|
api.nexthop_num = count;
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-08-21 02:18:36 +02:00
|
|
|
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2020-06-19 20:46:12 +02:00
|
|
|
void isis_zebra_route_del_route(struct isis *isis,
|
|
|
|
struct prefix *prefix,
|
2019-08-08 00:42:18 +02:00
|
|
|
struct prefix_ipv6 *src_p,
|
|
|
|
struct isis_route_info *route_info)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-08-21 02:18:36 +02:00
|
|
|
struct zapi_route api;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-08-08 00:42:18 +02:00
|
|
|
if (zclient->sock < 0)
|
2003-12-23 09:09:43 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 02:18:36 +02:00
|
|
|
memset(&api, 0, sizeof(api));
|
2020-06-19 20:46:12 +02:00
|
|
|
api.vrf_id = isis->vrf_id;
|
2018-03-22 15:01:08 +01:00
|
|
|
api.type = PROTO_TYPE;
|
2012-04-12 08:56:03 +02:00
|
|
|
api.safi = SAFI_UNICAST;
|
2017-08-21 02:18:36 +02:00
|
|
|
api.prefix = *prefix;
|
2018-07-26 22:53:08 +02:00
|
|
|
if (src_p && src_p->prefixlen) {
|
|
|
|
api.src_prefix = *src_p;
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
|
|
|
|
}
|
2004-09-10 22:48:21 +02:00
|
|
|
|
2017-08-21 02:18:36 +02:00
|
|
|
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2020-05-04 19:39:20 +02:00
|
|
|
/**
|
2020-09-20 07:39:28 +02:00
|
|
|
* Install Prefix-SID label entry in the forwarding plane through Zebra.
|
2020-05-04 19:39:20 +02:00
|
|
|
*
|
2020-09-20 07:39:28 +02:00
|
|
|
* @param area IS-IS area
|
|
|
|
* @param prefix Route prefix
|
|
|
|
* @param rinfo Route information
|
|
|
|
* @param psid Prefix-SID information
|
2020-05-04 19:39:20 +02:00
|
|
|
*/
|
2020-09-20 07:39:28 +02:00
|
|
|
void isis_zebra_prefix_sid_install(struct isis_area *area,
|
|
|
|
struct prefix *prefix,
|
|
|
|
struct isis_route_info *rinfo,
|
|
|
|
struct isis_sr_psid_info *psid)
|
2019-08-04 03:02:37 +02:00
|
|
|
{
|
|
|
|
struct zapi_labels zl;
|
2020-08-21 00:55:42 +02:00
|
|
|
int count = 0;
|
2019-08-04 03:02:37 +02:00
|
|
|
|
2020-09-20 07:39:28 +02:00
|
|
|
sr_debug("ISIS-Sr (%s): update label %u for prefix %pFX",
|
|
|
|
area->area_tag, psid->label, prefix);
|
|
|
|
|
2019-08-04 03:02:37 +02:00
|
|
|
/* Prepare message. */
|
|
|
|
memset(&zl, 0, sizeof(zl));
|
|
|
|
zl.type = ZEBRA_LSP_ISIS_SR;
|
2020-09-20 07:39:28 +02:00
|
|
|
zl.local_label = psid->label;
|
|
|
|
|
|
|
|
/* Local routes don't have any nexthop and require special handling. */
|
|
|
|
if (list_isempty(rinfo->nexthops)) {
|
|
|
|
struct zapi_nexthop *znh;
|
|
|
|
struct interface *ifp;
|
2019-08-04 03:02:37 +02:00
|
|
|
|
|
|
|
ifp = if_lookup_by_name("lo", VRF_DEFAULT);
|
|
|
|
if (!ifp) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: couldn't install Prefix-SID %pFX: loopback interface not found",
|
2020-09-20 07:39:28 +02:00
|
|
|
__func__, prefix);
|
2019-08-04 03:02:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
znh = &zl.nexthops[zl.nexthop_num++];
|
|
|
|
znh->type = NEXTHOP_TYPE_IFINDEX;
|
|
|
|
znh->ifindex = ifp->ifindex;
|
2020-03-03 16:59:33 +01:00
|
|
|
znh->label_num = 1;
|
|
|
|
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
|
2020-09-20 07:39:28 +02:00
|
|
|
} else {
|
2020-08-21 00:55:42 +02:00
|
|
|
/* Add backup nexthops first. */
|
|
|
|
if (rinfo->backup) {
|
|
|
|
count = isis_zebra_add_nexthops(
|
2020-09-20 07:39:28 +02:00
|
|
|
area->isis, rinfo->backup->nexthops,
|
|
|
|
zl.backup_nexthops, ISIS_NEXTHOP_BACKUP, true,
|
2020-08-21 00:55:42 +02:00
|
|
|
0);
|
|
|
|
if (count > 0) {
|
|
|
|
SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
|
|
|
|
zl.backup_nexthop_num = count;
|
|
|
|
}
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
2020-08-21 00:55:42 +02:00
|
|
|
|
|
|
|
/* Add primary nexthops. */
|
2020-09-20 07:39:28 +02:00
|
|
|
count = isis_zebra_add_nexthops(area->isis, rinfo->nexthops,
|
|
|
|
zl.nexthops, ISIS_NEXTHOP_MAIN,
|
|
|
|
true, count);
|
2020-08-21 00:55:42 +02:00
|
|
|
if (!count)
|
|
|
|
return;
|
|
|
|
zl.nexthop_num = count;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Send message to zebra. */
|
|
|
|
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
|
|
|
|
}
|
|
|
|
|
2020-05-04 19:39:20 +02:00
|
|
|
/**
|
2020-09-20 07:39:28 +02:00
|
|
|
* Uninstall Prefix-SID label entry from the forwarding plane through Zebra.
|
2020-05-04 19:39:20 +02:00
|
|
|
*
|
2020-09-20 07:39:28 +02:00
|
|
|
* @param area IS-IS area
|
|
|
|
* @param prefix Route prefix
|
|
|
|
* @param rinfo Route information
|
|
|
|
* @param psid Prefix-SID information
|
2020-05-04 19:39:20 +02:00
|
|
|
*/
|
2020-09-20 07:39:28 +02:00
|
|
|
void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
|
|
|
|
struct prefix *prefix,
|
|
|
|
struct isis_route_info *rinfo,
|
|
|
|
struct isis_sr_psid_info *psid)
|
2019-08-04 03:02:37 +02:00
|
|
|
{
|
|
|
|
struct zapi_labels zl;
|
|
|
|
|
2020-09-20 07:39:28 +02:00
|
|
|
sr_debug("ISIS-Sr (%s): delete label %u for prefix %pFX",
|
|
|
|
area->area_tag, psid->label, prefix);
|
|
|
|
|
2019-08-04 03:02:37 +02:00
|
|
|
/* Prepare message. */
|
|
|
|
memset(&zl, 0, sizeof(zl));
|
|
|
|
zl.type = ZEBRA_LSP_ISIS_SR;
|
2020-09-20 07:39:28 +02:00
|
|
|
zl.local_label = psid->label;
|
2019-08-04 03:02:37 +02:00
|
|
|
|
|
|
|
/* Send message to zebra. */
|
|
|
|
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
|
|
|
|
}
|
|
|
|
|
2020-05-04 19:39:20 +02:00
|
|
|
/**
|
|
|
|
* Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
|
|
|
|
*
|
|
|
|
* @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
|
|
|
|
* @param sra Segment Routing Adjacency-SID
|
|
|
|
*/
|
2020-05-04 18:26:21 +02:00
|
|
|
void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
|
|
|
|
{
|
2020-08-31 20:24:02 +02:00
|
|
|
struct isis *isis = sra->adj->circuit->area->isis;
|
2020-05-04 18:26:21 +02:00
|
|
|
struct zapi_labels zl;
|
|
|
|
struct zapi_nexthop *znh;
|
|
|
|
|
|
|
|
if (cmd != ZEBRA_MPLS_LABELS_ADD && cmd != ZEBRA_MPLS_LABELS_DELETE) {
|
|
|
|
flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
|
|
|
|
__func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr_debug(" |- %s label %u for interface %s",
|
|
|
|
cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
|
2020-08-31 20:24:02 +02:00
|
|
|
sra->input_label, sra->adj->circuit->interface->name);
|
2020-05-04 18:26:21 +02:00
|
|
|
|
|
|
|
memset(&zl, 0, sizeof(zl));
|
|
|
|
zl.type = ZEBRA_LSP_ISIS_SR;
|
2020-08-31 20:24:02 +02:00
|
|
|
zl.local_label = sra->input_label;
|
2020-05-04 18:26:21 +02:00
|
|
|
zl.nexthop_num = 1;
|
|
|
|
znh = &zl.nexthops[0];
|
|
|
|
znh->gate = sra->nexthop.address;
|
|
|
|
znh->type = (sra->nexthop.family == AF_INET)
|
|
|
|
? NEXTHOP_TYPE_IPV4_IFINDEX
|
|
|
|
: NEXTHOP_TYPE_IPV6_IFINDEX;
|
|
|
|
znh->ifindex = sra->adj->circuit->interface->ifindex;
|
|
|
|
znh->label_num = 1;
|
|
|
|
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
|
|
|
|
|
2020-08-31 20:24:02 +02:00
|
|
|
/* Set backup nexthops. */
|
|
|
|
if (sra->type == ISIS_SR_LAN_BACKUP) {
|
|
|
|
int count;
|
|
|
|
|
|
|
|
count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
|
|
|
|
zl.backup_nexthops,
|
2020-09-20 07:39:28 +02:00
|
|
|
ISIS_NEXTHOP_BACKUP, true, 0);
|
2020-08-31 20:24:02 +02:00
|
|
|
if (count > 0) {
|
|
|
|
SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
|
|
|
|
zl.backup_nexthop_num = count;
|
|
|
|
|
|
|
|
SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
|
|
|
|
znh->backup_num = count;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
znh->backup_idx[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:26:21 +02:00
|
|
|
(void)zebra_send_mpls_labels(zclient, cmd, &zl);
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2017-08-21 03:10:50 +02:00
|
|
|
struct zapi_route api;
|
2020-07-13 14:37:59 +02:00
|
|
|
struct isis *isis = NULL;
|
|
|
|
|
|
|
|
isis = isis_lookup_by_vrfid(vrf_id);
|
|
|
|
|
|
|
|
if (isis == NULL)
|
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-21 03:10:50 +02:00
|
|
|
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-02-22 16:20:51 +01:00
|
|
|
if (api.prefix.family == AF_INET6
|
|
|
|
&& IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
|
|
|
|
return 0;
|
|
|
|
|
2015-11-12 14:24:22 +01:00
|
|
|
/*
|
|
|
|
* Avoid advertising a false default reachability. (A default
|
|
|
|
* route installed by IS-IS gets redistributed from zebra back
|
|
|
|
* into IS-IS causing us to start advertising default reachabity
|
|
|
|
* without this check)
|
|
|
|
*/
|
2018-07-22 21:49:02 +02:00
|
|
|
if (api.prefix.prefixlen == 0
|
|
|
|
&& api.src_prefix.prefixlen == 0
|
2018-03-22 15:01:08 +01:00
|
|
|
&& api.type == PROTO_TYPE) {
|
2019-05-03 21:42:59 +02:00
|
|
|
cmd = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
|
2018-07-22 21:49:02 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
2020-07-13 14:37:59 +02:00
|
|
|
isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
|
2021-03-05 23:12:00 +01:00
|
|
|
api.distance, api.metric, api.tag);
|
2015-11-12 14:24:22 +01:00
|
|
|
else
|
2020-07-13 14:37:59 +02:00
|
|
|
isis_redist_delete(isis, api.type, &api.prefix,
|
|
|
|
&api.src_prefix);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-12-23 09:09:43 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int isis_distribute_list_update(int routetype)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-20 22:47:54 +02:00
|
|
|
void isis_zebra_redistribute_set(afi_t afi, int type)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2015-11-12 14:24:22 +01:00
|
|
|
if (type == DEFAULT_ROUTE)
|
|
|
|
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
2019-01-11 22:20:13 +01:00
|
|
|
zclient, afi, VRF_DEFAULT);
|
2015-11-12 14:24:22 +01:00
|
|
|
else
|
2017-06-20 22:47:54 +02:00
|
|
|
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
|
|
|
|
0, VRF_DEFAULT);
|
2015-11-12 14:24:22 +01:00
|
|
|
}
|
|
|
|
|
2017-06-20 22:47:54 +02:00
|
|
|
void isis_zebra_redistribute_unset(afi_t afi, int type)
|
2015-11-12 14:24:22 +01:00
|
|
|
{
|
|
|
|
if (type == DEFAULT_ROUTE)
|
|
|
|
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
|
2019-01-11 22:20:13 +01:00
|
|
|
zclient, afi, VRF_DEFAULT);
|
2015-11-12 14:24:22 +01:00
|
|
|
else
|
2017-06-20 22:47:54 +02:00
|
|
|
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
|
|
|
|
type, 0, VRF_DEFAULT);
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
|
|
|
|
2020-11-26 03:39:09 +01:00
|
|
|
/**
|
|
|
|
* Register RLFA with LDP.
|
|
|
|
*/
|
|
|
|
int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa)
|
|
|
|
{
|
|
|
|
struct isis_area *area = spftree->area;
|
|
|
|
struct zapi_rlfa_request zr = {};
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!zclient)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
zr.igp.vrf_id = area->isis->vrf_id;
|
|
|
|
zr.igp.protocol = ZEBRA_ROUTE_ISIS;
|
|
|
|
strlcpy(zr.igp.isis.area_tag, area->area_tag,
|
|
|
|
sizeof(zr.igp.isis.area_tag));
|
|
|
|
zr.igp.isis.spf.tree_id = spftree->tree_id;
|
|
|
|
zr.igp.isis.spf.level = spftree->level;
|
|
|
|
zr.igp.isis.spf.run_id = spftree->runcount;
|
|
|
|
zr.destination = rlfa->prefix;
|
|
|
|
zr.pq_address = rlfa->pq_address;
|
|
|
|
|
|
|
|
zlog_debug("ISIS-LFA: registering RLFA %pFX@%pI4 with LDP",
|
|
|
|
&rlfa->prefix, &rlfa->pq_address);
|
|
|
|
|
|
|
|
ret = zclient_send_opaque_unicast(zclient, LDP_RLFA_REGISTER,
|
|
|
|
ZEBRA_ROUTE_LDP, 0, 0,
|
|
|
|
(const uint8_t *)&zr, sizeof(zr));
|
|
|
|
if (ret == ZCLIENT_SEND_FAILURE) {
|
|
|
|
zlog_warn("ISIS-LFA: failed to register RLFA with LDP");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister all RLFAs from the given SPF tree with LDP.
|
|
|
|
*/
|
|
|
|
void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree)
|
|
|
|
{
|
|
|
|
struct isis_area *area = spftree->area;
|
|
|
|
struct zapi_rlfa_igp igp = {};
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!zclient || spftree->type != SPF_TYPE_FORWARD
|
|
|
|
|| CHECK_FLAG(spftree->flags, F_SPFTREE_NO_ADJACENCIES))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (IS_DEBUG_LFA)
|
|
|
|
zlog_debug("ISIS-LFA: unregistering all RLFAs with LDP");
|
|
|
|
|
|
|
|
igp.vrf_id = area->isis->vrf_id;
|
|
|
|
igp.protocol = ZEBRA_ROUTE_ISIS;
|
|
|
|
strlcpy(igp.isis.area_tag, area->area_tag, sizeof(igp.isis.area_tag));
|
|
|
|
igp.isis.spf.tree_id = spftree->tree_id;
|
|
|
|
igp.isis.spf.level = spftree->level;
|
|
|
|
igp.isis.spf.run_id = spftree->runcount;
|
|
|
|
|
|
|
|
ret = zclient_send_opaque_unicast(zclient, LDP_RLFA_UNREGISTER_ALL,
|
|
|
|
ZEBRA_ROUTE_LDP, 0, 0,
|
|
|
|
(const uint8_t *)&igp, sizeof(igp));
|
|
|
|
if (ret == ZCLIENT_SEND_FAILURE)
|
|
|
|
zlog_warn("ISIS-LFA: failed to unregister RLFA with LDP");
|
|
|
|
}
|
|
|
|
|
2020-04-10 17:12:48 +02:00
|
|
|
/* Label Manager Functions */
|
|
|
|
|
2020-06-04 18:03:04 +02:00
|
|
|
/**
|
|
|
|
* Check if Label Manager is Ready or not.
|
|
|
|
*
|
|
|
|
* @return True if Label Manager is ready, False otherwise
|
|
|
|
*/
|
|
|
|
bool isis_zebra_label_manager_ready(void)
|
|
|
|
{
|
|
|
|
return (zclient_sync->sock > 0);
|
|
|
|
}
|
|
|
|
|
2020-04-10 17:12:48 +02:00
|
|
|
/**
|
|
|
|
* Request Label Range to the Label Manager.
|
|
|
|
*
|
|
|
|
* @param base base label of the label range to request
|
|
|
|
* @param chunk_size size of the label range to request
|
|
|
|
*
|
|
|
|
* @return 0 on success, -1 on failure
|
|
|
|
*/
|
2019-08-04 03:02:37 +02:00
|
|
|
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
uint32_t start, end;
|
|
|
|
|
2020-06-04 18:03:04 +02:00
|
|
|
if (zclient_sync->sock < 0)
|
|
|
|
return -1;
|
2019-08-04 03:02:37 +02:00
|
|
|
|
|
|
|
ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
|
|
|
|
&end);
|
|
|
|
if (ret < 0) {
|
|
|
|
zlog_warn("%s: error getting label range!", __func__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-10 17:12:48 +02:00
|
|
|
/**
|
|
|
|
* Release Label Range to the Label Manager.
|
|
|
|
*
|
|
|
|
* @param start start of label range to release
|
|
|
|
* @param end end of label range to release
|
|
|
|
*
|
2020-06-04 18:03:04 +02:00
|
|
|
* @return 0 on success, -1 otherwise
|
2020-04-10 17:12:48 +02:00
|
|
|
*/
|
2020-06-04 18:03:04 +02:00
|
|
|
int isis_zebra_release_label_range(uint32_t start, uint32_t end)
|
2019-08-04 03:02:37 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2020-06-04 18:03:04 +02:00
|
|
|
if (zclient_sync->sock < 0)
|
2019-08-04 03:02:37 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = lm_release_label_chunk(zclient_sync, start, end);
|
|
|
|
if (ret < 0) {
|
|
|
|
zlog_warn("%s: error releasing label range!", __func__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-10 17:12:48 +02:00
|
|
|
/**
|
|
|
|
* Connect to the Label Manager.
|
2020-06-04 18:03:04 +02:00
|
|
|
*
|
|
|
|
* @return 0 on success, -1 otherwise
|
2020-04-10 17:12:48 +02:00
|
|
|
*/
|
2020-06-04 18:03:04 +02:00
|
|
|
int isis_zebra_label_manager_connect(void)
|
2019-08-04 03:02:37 +02:00
|
|
|
{
|
|
|
|
/* Connect to label manager. */
|
2020-06-04 18:03:04 +02:00
|
|
|
if (zclient_socket_connect(zclient_sync) < 0) {
|
|
|
|
zlog_warn("%s: failed connecting synchronous zclient!",
|
2019-08-04 03:02:37 +02:00
|
|
|
__func__);
|
2020-06-04 18:03:04 +02:00
|
|
|
return -1;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
2020-04-10 17:12:48 +02:00
|
|
|
/* make socket non-blocking */
|
2019-08-04 03:02:37 +02:00
|
|
|
set_nonblocking(zclient_sync->sock);
|
2020-04-10 17:12:48 +02:00
|
|
|
|
|
|
|
/* Send hello to notify zebra this is a synchronous client */
|
2020-11-11 20:14:37 +01:00
|
|
|
if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) {
|
2020-06-04 18:03:04 +02:00
|
|
|
zlog_warn("%s: failed sending hello for synchronous zclient!",
|
|
|
|
__func__);
|
|
|
|
close(zclient_sync->sock);
|
|
|
|
zclient_sync->sock = -1;
|
|
|
|
return -1;
|
2020-04-10 17:12:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect to label manager */
|
2020-06-04 18:03:04 +02:00
|
|
|
if (lm_label_manager_connect(zclient_sync, 0) != 0) {
|
|
|
|
zlog_warn("%s: failed connecting to label manager!", __func__);
|
|
|
|
if (zclient_sync->sock > 0) {
|
|
|
|
close(zclient_sync->sock);
|
|
|
|
zclient_sync->sock = -1;
|
|
|
|
}
|
|
|
|
return -1;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
|
|
|
|
2020-06-04 18:03:04 +02:00
|
|
|
sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
|
|
|
|
|
|
|
|
return 0;
|
2019-08-04 03:02:37 +02:00
|
|
|
}
|
|
|
|
|
2020-08-18 09:26:51 +02:00
|
|
|
void isis_zebra_vrf_register(struct isis *isis)
|
|
|
|
{
|
|
|
|
if (!zclient || zclient->sock < 0 || !isis)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isis->vrf_id != VRF_UNKNOWN) {
|
|
|
|
if (IS_DEBUG_EVENTS)
|
|
|
|
zlog_debug("%s: Register VRF %s id %u", __func__,
|
|
|
|
isis->name, isis->vrf_id);
|
|
|
|
zclient_send_reg_requests(zclient, isis->vrf_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
*: 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
|
|
|
static void isis_zebra_connected(struct zclient *zclient)
|
|
|
|
{
|
2016-02-12 20:37:33 +01:00
|
|
|
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
2020-11-26 03:39:09 +01:00
|
|
|
zclient_register_opaque(zclient, LDP_RLFA_LABELS);
|
*: 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
|
|
|
}
|
|
|
|
|
2020-07-22 20:32:35 +02:00
|
|
|
/*
|
|
|
|
* opaque messages between processes
|
|
|
|
*/
|
|
|
|
static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
|
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
struct zapi_opaque_msg info;
|
|
|
|
struct ldp_igp_sync_if_state state;
|
|
|
|
struct ldp_igp_sync_announce announce;
|
2020-11-26 03:39:09 +01:00
|
|
|
struct zapi_rlfa_response rlfa;
|
2020-07-22 20:32:35 +02:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
s = zclient->ibuf;
|
|
|
|
if (zclient_opaque_decode(s, &info) != 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (info.type) {
|
|
|
|
case LDP_IGP_SYNC_IF_STATE_UPDATE:
|
|
|
|
STREAM_GET(&state, s, sizeof(state));
|
|
|
|
ret = isis_ldp_sync_state_update(state);
|
|
|
|
break;
|
|
|
|
case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
|
|
|
|
STREAM_GET(&announce, s, sizeof(announce));
|
|
|
|
ret = isis_ldp_sync_announce_update(announce);
|
|
|
|
break;
|
2020-11-26 03:39:09 +01:00
|
|
|
case LDP_RLFA_LABELS:
|
|
|
|
STREAM_GET(&rlfa, s, sizeof(rlfa));
|
|
|
|
isis_rlfa_process_ldp_response(&rlfa);
|
|
|
|
break;
|
2020-07-22 20:32:35 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream_failure:
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-12-08 15:44:27 +01:00
|
|
|
static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
struct zapi_client_close_info info;
|
|
|
|
|
|
|
|
if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
isis_ldp_sync_handle_client_close(&info);
|
2020-11-26 03:39:09 +01:00
|
|
|
isis_ldp_rlfa_handle_client_close(&info);
|
2020-12-08 15:44:27 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-08-04 03:02:37 +02:00
|
|
|
void isis_zebra_init(struct thread_master *master, int instance)
|
2003-12-23 09:09:43 +01:00
|
|
|
{
|
2019-08-04 03:02:37 +02:00
|
|
|
/* Initialize asynchronous zclient. */
|
2018-11-02 13:54:58 +01:00
|
|
|
zclient = zclient_new(master, &zclient_options_default);
|
2018-03-22 15:01:08 +01:00
|
|
|
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
|
*: 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
|
|
|
zclient->zebra_connected = isis_zebra_connected;
|
2004-10-03 20:18:34 +02:00
|
|
|
zclient->router_id_update = isis_router_id_update_zebra;
|
2003-12-23 09:09:43 +01:00
|
|
|
zclient->interface_address_add = isis_zebra_if_address_add;
|
|
|
|
zclient->interface_address_delete = isis_zebra_if_address_del;
|
2016-04-19 19:03:05 +02:00
|
|
|
zclient->interface_link_params = isis_zebra_link_params;
|
2017-08-21 03:10:50 +02:00
|
|
|
zclient->redistribute_route_add = isis_zebra_read;
|
|
|
|
zclient->redistribute_route_del = isis_zebra_read;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-08-04 03:02:37 +02:00
|
|
|
/* Initialize special zclient for synchronous message exchanges. */
|
2020-04-10 17:12:48 +02:00
|
|
|
struct zclient_options options = zclient_options_default;
|
|
|
|
options.synchronous = true;
|
|
|
|
zclient_sync = zclient_new(master, &options);
|
2019-08-04 03:02:37 +02:00
|
|
|
zclient_sync->sock = -1;
|
|
|
|
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
|
|
|
|
zclient_sync->instance = instance;
|
2020-04-10 17:12:48 +02:00
|
|
|
/*
|
|
|
|
* session_id must be different from default value (0) to distinguish
|
|
|
|
* the asynchronous socket from the synchronous one
|
|
|
|
*/
|
|
|
|
zclient_sync->session_id = 1;
|
2019-08-04 03:02:37 +02:00
|
|
|
zclient_sync->privs = &isisd_privs;
|
2020-07-22 20:32:35 +02:00
|
|
|
|
|
|
|
zclient->opaque_msg_handler = isis_opaque_msg_handler;
|
2020-12-08 15:44:27 +01:00
|
|
|
|
|
|
|
zclient->zebra_client_close_notify = isis_zebra_client_close_notify;
|
2003-12-23 09:09:43 +01:00
|
|
|
}
|
2017-06-30 16:31:09 +02:00
|
|
|
|
|
|
|
void isis_zebra_stop(void)
|
|
|
|
{
|
2020-11-26 03:39:09 +01:00
|
|
|
zclient_unregister_opaque(zclient, LDP_RLFA_LABELS);
|
2020-06-04 18:03:04 +02:00
|
|
|
zclient_stop(zclient_sync);
|
|
|
|
zclient_free(zclient_sync);
|
2017-06-30 16:31:09 +02:00
|
|
|
zclient_stop(zclient);
|
|
|
|
zclient_free(zclient);
|
2017-09-12 04:05:16 +02:00
|
|
|
frr_fini();
|
2017-06-30 16:31:09 +02:00
|
|
|
}
|