2018-05-08 13:58:32 +02:00
|
|
|
/*
|
|
|
|
* Zebra connect code.
|
|
|
|
* Copyright (C) 2018 Cumulus Networks, Inc.
|
|
|
|
* Donald Sharp
|
|
|
|
*
|
2018-06-21 14:46:05 +02:00
|
|
|
* This program 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 of the License, or (at your option)
|
|
|
|
* any later version.
|
2018-05-08 13:58:32 +02:00
|
|
|
*
|
2018-06-21 14:46:05 +02:00
|
|
|
* 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.
|
2018-05-08 13:58:32 +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
|
|
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "routemap.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "srcdest_table.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "zclient.h"
|
|
|
|
#include "filter.h"
|
|
|
|
#include "plist.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "nexthop.h"
|
|
|
|
#include "nexthop_group.h"
|
2018-08-25 02:42:45 +02:00
|
|
|
#include "hash.h"
|
2018-08-29 04:45:06 +02:00
|
|
|
#include "jhash.h"
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
#include "static_vrf.h"
|
|
|
|
#include "static_routes.h"
|
|
|
|
#include "static_zebra.h"
|
|
|
|
#include "static_nht.h"
|
|
|
|
#include "static_vty.h"
|
|
|
|
|
2019-07-16 13:31:18 +02:00
|
|
|
bool debug;
|
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
/* Zebra structure to hold current status. */
|
|
|
|
struct zclient *zclient;
|
2018-08-25 02:42:45 +02:00
|
|
|
static struct hash *static_nht_hash;
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
/* Inteface addition message from zebra. */
|
2019-09-19 04:26:55 +02:00
|
|
|
static int static_ifp_create(struct interface *ifp)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
|
|
|
static_ifindex_update(ifp, true);
|
2019-09-19 04:26:55 +02:00
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 15:40:57 +02:00
|
|
|
static int static_ifp_destroy(struct interface *ifp)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
|
|
|
static_ifindex_update(ifp, false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int interface_address_add(ZAPI_CALLBACK_ARGS)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2019-05-03 21:42:59 +02:00
|
|
|
zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int interface_address_delete(ZAPI_CALLBACK_ARGS)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
|
|
|
struct connected *c;
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
if (!c)
|
|
|
|
return 0;
|
|
|
|
|
2019-10-30 01:16:28 +01:00
|
|
|
connected_free(&c);
|
2018-05-08 13:58:32 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 05:07:44 +02:00
|
|
|
static int static_ifp_up(struct interface *ifp)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2019-09-19 05:07:44 +02:00
|
|
|
if (if_is_vrf(ifp)) {
|
|
|
|
struct static_vrf *svrf = static_vrf_lookup_by_id(ifp->vrf_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
|
2019-09-19 05:07:44 +02:00
|
|
|
static_fixup_vrf_ids(svrf);
|
2018-05-08 13:58:32 +02:00
|
|
|
}
|
|
|
|
|
2019-09-19 05:07:44 +02:00
|
|
|
/* Install any static reliant on this interface coming up */
|
|
|
|
static_install_intf_nh(ifp);
|
|
|
|
static_ifindex_update(ifp, true);
|
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 05:55:34 +02:00
|
|
|
static int static_ifp_down(struct interface *ifp)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2019-09-19 05:55:34 +02:00
|
|
|
static_ifindex_update(ifp, false);
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:42:59 +02:00
|
|
|
static int route_notify_owner(ZAPI_CALLBACK_ARGS)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
enum zapi_route_notify_owner note;
|
|
|
|
uint32_t table_id;
|
|
|
|
char buf[PREFIX_STRLEN];
|
|
|
|
|
|
|
|
if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e))
|
|
|
|
return -1;
|
|
|
|
|
2018-12-28 03:46:01 +01:00
|
|
|
prefix2str(&p, buf, sizeof(buf));
|
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
switch (note) {
|
|
|
|
case ZAPI_ROUTE_FAIL_INSTALL:
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
2018-05-08 13:58:32 +02:00
|
|
|
zlog_warn("%s: Route %s failed to install for table: %u",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, buf, table_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case ZAPI_ROUTE_BETTER_ADMIN_WON:
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn(
|
|
|
|
"%s: Route %s over-ridden by better route for table: %u",
|
|
|
|
__func__, buf, table_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case ZAPI_ROUTE_INSTALLED:
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case ZAPI_ROUTE_REMOVED:
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case ZAPI_ROUTE_REMOVE_FAIL:
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
|
2018-05-08 13:58:32 +02:00
|
|
|
zlog_warn("%s: Route %s failure to remove for table: %u",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, buf, table_id);
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static void zebra_connected(struct zclient *zclient)
|
|
|
|
{
|
|
|
|
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
|
|
|
}
|
|
|
|
|
2018-08-25 02:42:45 +02:00
|
|
|
struct static_nht_data {
|
|
|
|
struct prefix *nh;
|
2018-08-29 04:45:06 +02:00
|
|
|
|
|
|
|
vrf_id_t nh_vrf_id;
|
|
|
|
|
2018-08-25 02:42:45 +02:00
|
|
|
uint32_t refcount;
|
|
|
|
uint8_t nh_num;
|
|
|
|
};
|
2018-05-08 13:58:32 +02:00
|
|
|
|
2019-05-10 07:35:48 +02:00
|
|
|
/* API to check whether the configured nexthop address is
|
|
|
|
* one of its local connected address or not.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
static_nexthop_is_local(vrf_id_t vrfid, struct prefix *addr, int family)
|
|
|
|
{
|
|
|
|
if (family == AF_INET) {
|
|
|
|
if (if_lookup_exact_address(&addr->u.prefix4,
|
|
|
|
AF_INET,
|
|
|
|
vrfid))
|
|
|
|
return true;
|
|
|
|
} else if (family == AF_INET6) {
|
|
|
|
if (if_lookup_exact_address(&addr->u.prefix6,
|
|
|
|
AF_INET6,
|
|
|
|
vrfid))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2019-05-03 21:42:59 +02:00
|
|
|
static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2018-08-25 02:42:45 +02:00
|
|
|
struct static_nht_data *nhtd, lookup;
|
2018-05-08 13:58:32 +02:00
|
|
|
struct zapi_route nhr;
|
|
|
|
afi_t afi = AFI_IP;
|
|
|
|
|
|
|
|
if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
|
|
|
|
zlog_warn("Failure to decode nexthop update message");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nhr.prefix.family == AF_INET6)
|
|
|
|
afi = AFI_IP6;
|
|
|
|
|
2019-05-10 07:35:48 +02:00
|
|
|
if (nhr.type == ZEBRA_ROUTE_CONNECT) {
|
|
|
|
if (static_nexthop_is_local(vrf_id, &nhr.prefix,
|
|
|
|
nhr.prefix.family))
|
|
|
|
nhr.nexthop_num = 0;
|
|
|
|
}
|
|
|
|
|
2018-08-25 02:42:45 +02:00
|
|
|
memset(&lookup, 0, sizeof(lookup));
|
|
|
|
lookup.nh = &nhr.prefix;
|
2018-08-29 04:45:06 +02:00
|
|
|
lookup.nh_vrf_id = vrf_id;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
|
|
|
nhtd = hash_lookup(static_nht_hash, &lookup);
|
2018-08-29 04:45:06 +02:00
|
|
|
|
|
|
|
if (nhtd) {
|
2018-08-25 02:42:45 +02:00
|
|
|
nhtd->nh_num = nhr.nexthop_num;
|
|
|
|
|
2019-07-16 14:27:31 +02:00
|
|
|
static_nht_reset_start(&nhr.prefix, afi, nhtd->nh_vrf_id);
|
2019-07-15 22:26:17 +02:00
|
|
|
static_nht_update(NULL, &nhr.prefix, nhr.nexthop_num, afi,
|
2018-08-29 04:45:06 +02:00
|
|
|
nhtd->nh_vrf_id);
|
|
|
|
} else
|
|
|
|
zlog_err("No nhtd?");
|
2018-08-25 02:42:45 +02:00
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void static_zebra_capabilities(struct zclient_capabilities *cap)
|
|
|
|
{
|
|
|
|
mpls_enabled = cap->mpls_enabled;
|
|
|
|
}
|
|
|
|
|
2019-05-14 22:19:07 +02:00
|
|
|
static unsigned int static_nht_hash_key(const void *data)
|
2018-08-25 02:42:45 +02:00
|
|
|
{
|
2019-05-14 22:19:07 +02:00
|
|
|
const struct static_nht_data *nhtd = data;
|
2018-08-29 04:45:06 +02:00
|
|
|
unsigned int key = 0;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
2018-08-29 04:45:06 +02:00
|
|
|
key = prefix_hash_key(nhtd->nh);
|
|
|
|
return jhash_1word(nhtd->nh_vrf_id, key);
|
2018-08-25 02:42:45 +02:00
|
|
|
}
|
|
|
|
|
2018-10-17 21:27:12 +02:00
|
|
|
static bool static_nht_hash_cmp(const void *d1, const void *d2)
|
2018-08-25 02:42:45 +02:00
|
|
|
{
|
|
|
|
const struct static_nht_data *nhtd1 = d1;
|
|
|
|
const struct static_nht_data *nhtd2 = d2;
|
|
|
|
|
2018-08-29 04:45:06 +02:00
|
|
|
if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
|
2018-10-17 21:27:12 +02:00
|
|
|
return false;
|
2018-08-29 04:45:06 +02:00
|
|
|
|
2018-08-25 02:42:45 +02:00
|
|
|
return prefix_same(nhtd1->nh, nhtd2->nh);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *static_nht_hash_alloc(void *data)
|
|
|
|
{
|
|
|
|
struct static_nht_data *copy = data;
|
|
|
|
struct static_nht_data *new;
|
|
|
|
|
|
|
|
new = XMALLOC(MTYPE_TMP, sizeof(*new));
|
|
|
|
|
|
|
|
new->nh = prefix_new();
|
|
|
|
prefix_copy(new->nh, copy->nh);
|
|
|
|
new->refcount = 0;
|
|
|
|
new->nh_num = 0;
|
2018-08-29 04:45:06 +02:00
|
|
|
new->nh_vrf_id = copy->nh_vrf_id;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void static_nht_hash_free(void *data)
|
|
|
|
{
|
|
|
|
struct static_nht_data *nhtd = data;
|
|
|
|
|
2019-10-30 01:05:27 +01:00
|
|
|
prefix_free(&nhtd->nh);
|
2018-08-25 02:42:45 +02:00
|
|
|
XFREE(MTYPE_TMP, nhtd);
|
|
|
|
}
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
void static_zebra_nht_register(struct route_node *rn, struct static_nexthop *nh,
|
|
|
|
bool reg)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2018-08-25 02:42:45 +02:00
|
|
|
struct static_nht_data *nhtd, lookup;
|
2018-05-08 13:58:32 +02:00
|
|
|
uint32_t cmd;
|
|
|
|
struct prefix p;
|
2018-08-25 02:42:45 +02:00
|
|
|
afi_t afi = AFI_IP;
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
cmd = (reg) ?
|
|
|
|
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->nh_registered && reg)
|
2018-05-08 13:58:32 +02:00
|
|
|
return;
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
if (!nh->nh_registered && !reg)
|
2018-05-08 13:58:32 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
memset(&p, 0, sizeof(p));
|
2020-04-24 14:38:43 +02:00
|
|
|
switch (nh->type) {
|
2018-05-08 13:58:32 +02:00
|
|
|
case STATIC_IFNAME:
|
|
|
|
case STATIC_BLACKHOLE:
|
|
|
|
return;
|
|
|
|
case STATIC_IPV4_GATEWAY:
|
2018-05-08 16:58:30 +02:00
|
|
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
2018-05-08 13:58:32 +02:00
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
2020-04-24 14:38:43 +02:00
|
|
|
p.u.prefix4 = nh->addr.ipv4;
|
2018-08-25 02:42:45 +02:00
|
|
|
afi = AFI_IP;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case STATIC_IPV6_GATEWAY:
|
2018-05-08 16:58:30 +02:00
|
|
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
2018-05-08 13:58:32 +02:00
|
|
|
p.family = AF_INET6;
|
|
|
|
p.prefixlen = IPV6_MAX_BITLEN;
|
2020-04-24 14:38:43 +02:00
|
|
|
p.u.prefix6 = nh->addr.ipv6;
|
2018-08-25 02:42:45 +02:00
|
|
|
afi = AFI_IP6;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-08-25 02:42:45 +02:00
|
|
|
memset(&lookup, 0, sizeof(lookup));
|
|
|
|
lookup.nh = &p;
|
2020-04-24 14:38:43 +02:00
|
|
|
lookup.nh_vrf_id = nh->nh_vrf_id;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
nh->nh_registered = reg;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
|
|
|
if (reg) {
|
|
|
|
nhtd = hash_get(static_nht_hash, &lookup,
|
|
|
|
static_nht_hash_alloc);
|
|
|
|
nhtd->refcount++;
|
|
|
|
|
2019-07-16 13:31:18 +02:00
|
|
|
if (debug)
|
|
|
|
zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p,
|
|
|
|
rn, nhtd->nh_num);
|
|
|
|
if (nhtd->refcount > 1 && nhtd->nh_num) {
|
2020-04-24 14:38:43 +02:00
|
|
|
static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
|
|
|
|
nh->nh_vrf_id);
|
2018-08-25 02:42:45 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nhtd = hash_lookup(static_nht_hash, &lookup);
|
|
|
|
if (!nhtd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nhtd->refcount--;
|
|
|
|
if (nhtd->refcount >= 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
hash_release(static_nht_hash, nhtd);
|
|
|
|
static_nht_hash_free(nhtd);
|
|
|
|
}
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) < 0)
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
2018-05-08 13:58:32 +02:00
|
|
|
}
|
2020-04-24 14:38:43 +02:00
|
|
|
/*
|
|
|
|
* When nexthop gets updated via configuration then use the
|
|
|
|
* already registered NH and resend the route to zebra
|
|
|
|
*/
|
|
|
|
int static_zebra_nh_update(struct route_node *rn, struct static_nexthop *nh)
|
|
|
|
{
|
|
|
|
struct static_nht_data *nhtd, lookup = {};
|
|
|
|
struct prefix p = {};
|
|
|
|
afi_t afi = AFI_IP;
|
|
|
|
|
|
|
|
if (!nh->nh_registered)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (nh->type) {
|
|
|
|
case STATIC_IFNAME:
|
|
|
|
case STATIC_BLACKHOLE:
|
|
|
|
return 0;
|
|
|
|
case STATIC_IPV4_GATEWAY:
|
|
|
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
p.u.prefix4 = nh->addr.ipv4;
|
|
|
|
afi = AFI_IP;
|
|
|
|
break;
|
|
|
|
case STATIC_IPV6_GATEWAY:
|
|
|
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
|
|
|
p.family = AF_INET6;
|
|
|
|
p.prefixlen = IPV6_MAX_BITLEN;
|
|
|
|
p.u.prefix6 = nh->addr.ipv6;
|
|
|
|
afi = AFI_IP6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
lookup.nh = &p;
|
|
|
|
lookup.nh_vrf_id = nh->nh_vrf_id;
|
|
|
|
|
|
|
|
nhtd = hash_lookup(static_nht_hash, &lookup);
|
|
|
|
if (nhtd && nhtd->nh_num) {
|
|
|
|
nh->state = STATIC_START;
|
|
|
|
static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
|
|
|
|
nh->nh_vrf_id);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-05-08 13:58:32 +02:00
|
|
|
|
2018-06-22 03:55:38 +02:00
|
|
|
extern void static_zebra_route_add(struct route_node *rn,
|
2020-04-24 14:38:43 +02:00
|
|
|
struct static_path *pn, safi_t safi,
|
|
|
|
bool install)
|
2018-05-08 13:58:32 +02:00
|
|
|
{
|
2020-04-24 14:38:43 +02:00
|
|
|
struct static_nexthop *nh;
|
2018-05-08 13:58:32 +02:00
|
|
|
const struct prefix *p, *src_pp;
|
|
|
|
struct zapi_nexthop *api_nh;
|
|
|
|
struct zapi_route api;
|
|
|
|
uint32_t nh_num = 0;
|
2020-04-24 14:38:43 +02:00
|
|
|
struct stable_info *info;
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
p = src_pp = NULL;
|
|
|
|
srcdest_rnode_prefixes(rn, &p, &src_pp);
|
|
|
|
|
|
|
|
memset(&api, 0, sizeof(api));
|
2020-04-24 14:38:43 +02:00
|
|
|
info = static_get_stable_info(rn);
|
|
|
|
api.vrf_id = GET_STABLE_VRF_ID(info);
|
2018-05-08 13:58:32 +02:00
|
|
|
api.type = ZEBRA_ROUTE_STATIC;
|
|
|
|
api.safi = safi;
|
|
|
|
memcpy(&api.prefix, p, sizeof(api.prefix));
|
|
|
|
|
|
|
|
if (src_pp) {
|
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
|
|
|
|
memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
|
|
|
|
}
|
2018-06-22 03:55:38 +02:00
|
|
|
SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
|
2020-05-08 22:22:54 +02:00
|
|
|
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
|
2018-05-08 13:58:32 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
2020-04-24 14:38:43 +02:00
|
|
|
if (pn->distance) {
|
2018-06-22 03:55:38 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
2020-04-24 14:38:43 +02:00
|
|
|
api.distance = pn->distance;
|
2018-06-22 03:55:38 +02:00
|
|
|
}
|
2020-04-24 14:38:43 +02:00
|
|
|
if (pn->tag) {
|
2018-06-22 03:55:38 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
2020-04-24 14:38:43 +02:00
|
|
|
api.tag = pn->tag;
|
2018-06-22 03:55:38 +02:00
|
|
|
}
|
2020-04-24 14:38:43 +02:00
|
|
|
if (pn->table_id != 0) {
|
2018-08-22 10:04:06 +02:00
|
|
|
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
|
2020-04-24 14:38:43 +02:00
|
|
|
api.tableid = pn->table_id;
|
2018-08-22 10:04:06 +02:00
|
|
|
}
|
2020-04-24 14:38:43 +02:00
|
|
|
frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
|
2018-05-08 13:58:32 +02:00
|
|
|
api_nh = &api.nexthops[nh_num];
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->nh_vrf_id == VRF_UNKNOWN)
|
staticd: Allow table_id to be a distinguisher for installation
The table_id should be a discriminator in the installation of
static routes into zebra from staticd. Add this to allow the end
user to do something like this:
ip route 4.5.6.7/32 192.168.209.44
ip route 4.5.6.7/32 192.168.209.44 table 3000
ip route 4.5.6.7/32 192.168.209.45 table 3000
robot# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route
K>* 0.0.0.0/0 [0/101] via 192.168.201.1, enp0s3, 00:01:40
S>* 4.3.2.1/32 [1/0] via 192.168.210.4, enp0s10, 00:01:35
S>* 4.3.2.2/32 [1/0] via 192.168.209.4, enp0s9, 00:01:35
S>* 4.5.6.0/26 [1/0] via 192.168.210.4, enp0s10, 00:01:35
S>* 4.5.6.7/32 [1/0] via 192.168.209.44, enp0s9, 00:01:35
C>* 192.168.201.0/24 is directly connected, enp0s3, 00:01:40
C>* 192.168.208.0/24 is directly connected, enp0s8, 00:01:40
C>* 192.168.209.0/24 is directly connected, enp0s9, 00:01:40
C>* 192.168.210.0/24 is directly connected, enp0s10, 00:01:40
robot# show ip route table 3000
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route
S>* 4.5.6.7/32 [1/0] via 192.168.209.44, enp0s9, 00:00:55
* via 192.168.209.45, enp0s9, 00:00:55
robot#
Fixes: #2954
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2018-09-14 22:30:17 +02:00
|
|
|
continue;
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->vrf_id = nh->nh_vrf_id;
|
|
|
|
if (nh->onlink)
|
2019-11-13 22:06:06 +01:00
|
|
|
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
|
2019-01-27 02:44:42 +01:00
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
nh->state = STATIC_SENT_TO_ZEBRA;
|
2019-07-16 14:27:31 +02:00
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
switch (nh->type) {
|
2018-05-08 13:58:32 +02:00
|
|
|
case STATIC_IFNAME:
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->ifindex == IFINDEX_INTERNAL)
|
2018-05-08 13:58:32 +02:00
|
|
|
continue;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->ifindex = nh->ifindex;
|
2018-05-08 13:58:32 +02:00
|
|
|
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
|
|
|
break;
|
|
|
|
case STATIC_IPV4_GATEWAY:
|
2020-04-24 14:38:43 +02:00
|
|
|
if (!nh->nh_valid)
|
2018-05-08 13:58:32 +02:00
|
|
|
continue;
|
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV4;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->gate = nh->addr;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->ifindex == IFINDEX_INTERNAL)
|
2018-05-08 13:58:32 +02:00
|
|
|
continue;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->ifindex = nh->ifindex;
|
2018-05-08 13:58:32 +02:00
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->gate = nh->addr;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case STATIC_IPV6_GATEWAY:
|
2020-04-24 14:38:43 +02:00
|
|
|
if (!nh->nh_valid)
|
2018-05-08 13:58:32 +02:00
|
|
|
continue;
|
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV6;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->gate = nh->addr;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->ifindex == IFINDEX_INTERNAL)
|
2018-05-08 13:58:32 +02:00
|
|
|
continue;
|
|
|
|
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->ifindex = nh->ifindex;
|
|
|
|
api_nh->gate = nh->addr;
|
2018-05-08 13:58:32 +02:00
|
|
|
break;
|
|
|
|
case STATIC_BLACKHOLE:
|
|
|
|
api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
|
2020-04-24 14:38:43 +02:00
|
|
|
switch (nh->bh_type) {
|
2018-05-08 13:58:32 +02:00
|
|
|
case STATIC_BLACKHOLE_DROP:
|
|
|
|
case STATIC_BLACKHOLE_NULL:
|
|
|
|
api_nh->bh_type = BLACKHOLE_NULL;
|
|
|
|
break;
|
|
|
|
case STATIC_BLACKHOLE_REJECT:
|
|
|
|
api_nh->bh_type = BLACKHOLE_REJECT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-04-24 14:38:43 +02:00
|
|
|
if (nh->snh_label.num_labels) {
|
2018-05-08 13:58:32 +02:00
|
|
|
int i;
|
|
|
|
|
2019-11-13 22:06:06 +01:00
|
|
|
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->label_num = nh->snh_label.num_labels;
|
2018-05-08 13:58:32 +02:00
|
|
|
for (i = 0; i < api_nh->label_num; i++)
|
2020-04-24 14:38:43 +02:00
|
|
|
api_nh->labels[i] = nh->snh_label.label[i];
|
2018-05-08 13:58:32 +02:00
|
|
|
}
|
|
|
|
nh_num++;
|
|
|
|
}
|
|
|
|
|
|
|
|
api.nexthop_num = nh_num;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have been given an install but nothing is valid
|
|
|
|
* go ahead and delete the route for double plus fun
|
|
|
|
*/
|
|
|
|
if (!nh_num && install)
|
|
|
|
install = false;
|
|
|
|
|
|
|
|
zclient_route_send(install ?
|
|
|
|
ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
|
|
|
|
zclient, &api);
|
|
|
|
}
|
2019-09-18 22:20:04 +02:00
|
|
|
|
2018-05-08 13:58:32 +02:00
|
|
|
void static_zebra_init(void)
|
|
|
|
{
|
|
|
|
struct zclient_options opt = { .receive_notify = true };
|
|
|
|
|
2019-09-18 22:20:04 +02:00
|
|
|
if_zapi_callbacks(static_ifp_create, static_ifp_up,
|
|
|
|
static_ifp_down, static_ifp_destroy);
|
|
|
|
|
2018-11-02 13:54:58 +01:00
|
|
|
zclient = zclient_new(master, &opt);
|
2018-05-08 13:58:32 +02:00
|
|
|
|
|
|
|
zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
|
|
|
|
zclient->zebra_capabilities = static_zebra_capabilities;
|
|
|
|
zclient->zebra_connected = zebra_connected;
|
|
|
|
zclient->interface_address_add = interface_address_add;
|
|
|
|
zclient->interface_address_delete = interface_address_delete;
|
|
|
|
zclient->route_notify_owner = route_notify_owner;
|
|
|
|
zclient->nexthop_update = static_zebra_nexthop_update;
|
2018-08-25 02:42:45 +02:00
|
|
|
|
|
|
|
static_nht_hash = hash_create(static_nht_hash_key,
|
|
|
|
static_nht_hash_cmp,
|
|
|
|
"Static Nexthop Tracking hash");
|
2018-05-08 13:58:32 +02:00
|
|
|
}
|
2019-08-26 13:36:16 +02:00
|
|
|
|
|
|
|
void static_zebra_vrf_register(struct vrf *vrf)
|
|
|
|
{
|
|
|
|
if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
return;
|
|
|
|
zclient_send_reg_requests(zclient, vrf->vrf_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void static_zebra_vrf_unregister(struct vrf *vrf)
|
|
|
|
{
|
|
|
|
if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
return;
|
|
|
|
zclient_send_dereg_requests(zclient, vrf->vrf_id);
|
|
|
|
}
|