mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 16:20:08 +00:00
Merge branch 'frr/pull/133' ("Pim cleanup")
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
commit
26df3a33ae
@ -377,6 +377,7 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
|
||||
bgp_unlock_node (rn);
|
||||
bnc->last_update = bgp_clock();
|
||||
bnc->change_flags = 0;
|
||||
stream_getc (s); // Distance but not currently used
|
||||
metric = stream_getl (s);
|
||||
nexthop_num = stream_getc (s);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "zclient.h"
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "command.h"
|
||||
|
@ -37,6 +37,62 @@
|
||||
/* Zebra header size. */
|
||||
#define ZEBRA_HEADER_SIZE 8
|
||||
|
||||
/* Zebra message types. */
|
||||
typedef enum {
|
||||
ZEBRA_INTERFACE_ADD,
|
||||
ZEBRA_INTERFACE_DELETE,
|
||||
ZEBRA_INTERFACE_ADDRESS_ADD,
|
||||
ZEBRA_INTERFACE_ADDRESS_DELETE,
|
||||
ZEBRA_INTERFACE_UP,
|
||||
ZEBRA_INTERFACE_DOWN,
|
||||
ZEBRA_IPV4_ROUTE_ADD,
|
||||
ZEBRA_IPV4_ROUTE_DELETE,
|
||||
ZEBRA_IPV6_ROUTE_ADD,
|
||||
ZEBRA_IPV6_ROUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_ADD,
|
||||
ZEBRA_REDISTRIBUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
||||
ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
|
||||
ZEBRA_ROUTER_ID_ADD,
|
||||
ZEBRA_ROUTER_ID_DELETE,
|
||||
ZEBRA_ROUTER_ID_UPDATE,
|
||||
ZEBRA_HELLO,
|
||||
ZEBRA_NEXTHOP_REGISTER,
|
||||
ZEBRA_NEXTHOP_UNREGISTER,
|
||||
ZEBRA_NEXTHOP_UPDATE,
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
|
||||
ZEBRA_INTERFACE_BFD_DEST_UPDATE,
|
||||
ZEBRA_IMPORT_ROUTE_REGISTER,
|
||||
ZEBRA_IMPORT_ROUTE_UNREGISTER,
|
||||
ZEBRA_IMPORT_CHECK_UPDATE,
|
||||
ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD,
|
||||
ZEBRA_BFD_DEST_REGISTER,
|
||||
ZEBRA_BFD_DEST_DEREGISTER,
|
||||
ZEBRA_BFD_DEST_UPDATE,
|
||||
ZEBRA_BFD_DEST_REPLAY,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_DEL,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_DEL,
|
||||
ZEBRA_VRF_UNREGISTER,
|
||||
ZEBRA_VRF_ADD,
|
||||
ZEBRA_VRF_DELETE,
|
||||
ZEBRA_INTERFACE_VRF_UPDATE,
|
||||
ZEBRA_BFD_CLIENT_REGISTER,
|
||||
ZEBRA_INTERFACE_ENABLE_RADV,
|
||||
ZEBRA_INTERFACE_DISABLE_RADV,
|
||||
ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB,
|
||||
ZEBRA_INTERFACE_LINK_PARAMS,
|
||||
ZEBRA_MPLS_LABELS_ADD,
|
||||
ZEBRA_MPLS_LABELS_DELETE,
|
||||
ZEBRA_IPV4_NEXTHOP_ADD,
|
||||
ZEBRA_IPV4_NEXTHOP_DELETE,
|
||||
ZEBRA_IPV6_NEXTHOP_ADD,
|
||||
ZEBRA_IPV6_NEXTHOP_DELETE,
|
||||
ZEBRA_IPMR_ROUTE_STATS,
|
||||
} zebra_message_types_t;
|
||||
|
||||
struct redist_proto
|
||||
{
|
||||
u_char enabled;
|
||||
|
64
lib/zebra.h
64
lib/zebra.h
@ -352,62 +352,6 @@ struct in_pktinfo
|
||||
/* default zebra TCP port for zclient */
|
||||
#define ZEBRA_PORT 2600
|
||||
|
||||
/* Zebra message types. */
|
||||
typedef enum {
|
||||
ZEBRA_INTERFACE_ADD,
|
||||
ZEBRA_INTERFACE_DELETE,
|
||||
ZEBRA_INTERFACE_ADDRESS_ADD,
|
||||
ZEBRA_INTERFACE_ADDRESS_DELETE,
|
||||
ZEBRA_INTERFACE_UP,
|
||||
ZEBRA_INTERFACE_DOWN,
|
||||
ZEBRA_IPV4_ROUTE_ADD,
|
||||
ZEBRA_IPV4_ROUTE_DELETE,
|
||||
ZEBRA_IPV6_ROUTE_ADD,
|
||||
ZEBRA_IPV6_ROUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_ADD,
|
||||
ZEBRA_REDISTRIBUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
||||
ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
|
||||
ZEBRA_ROUTER_ID_ADD,
|
||||
ZEBRA_ROUTER_ID_DELETE,
|
||||
ZEBRA_ROUTER_ID_UPDATE,
|
||||
ZEBRA_HELLO,
|
||||
ZEBRA_NEXTHOP_REGISTER,
|
||||
ZEBRA_NEXTHOP_UNREGISTER,
|
||||
ZEBRA_NEXTHOP_UPDATE,
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
|
||||
ZEBRA_INTERFACE_BFD_DEST_UPDATE,
|
||||
ZEBRA_IMPORT_ROUTE_REGISTER,
|
||||
ZEBRA_IMPORT_ROUTE_UNREGISTER,
|
||||
ZEBRA_IMPORT_CHECK_UPDATE,
|
||||
ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD,
|
||||
ZEBRA_BFD_DEST_REGISTER,
|
||||
ZEBRA_BFD_DEST_DEREGISTER,
|
||||
ZEBRA_BFD_DEST_UPDATE,
|
||||
ZEBRA_BFD_DEST_REPLAY,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_DEL,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_DEL,
|
||||
ZEBRA_VRF_UNREGISTER,
|
||||
ZEBRA_VRF_ADD,
|
||||
ZEBRA_VRF_DELETE,
|
||||
ZEBRA_INTERFACE_VRF_UPDATE,
|
||||
ZEBRA_BFD_CLIENT_REGISTER,
|
||||
ZEBRA_INTERFACE_ENABLE_RADV,
|
||||
ZEBRA_INTERFACE_DISABLE_RADV,
|
||||
ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB,
|
||||
ZEBRA_INTERFACE_LINK_PARAMS,
|
||||
ZEBRA_MPLS_LABELS_ADD,
|
||||
ZEBRA_MPLS_LABELS_DELETE,
|
||||
ZEBRA_IPV4_NEXTHOP_ADD,
|
||||
ZEBRA_IPV4_NEXTHOP_DELETE,
|
||||
ZEBRA_IPV6_NEXTHOP_ADD,
|
||||
ZEBRA_IPV6_NEXTHOP_DELETE,
|
||||
ZEBRA_IPMR_ROUTE_STATS,
|
||||
} zebra_message_types_t;
|
||||
|
||||
/* Marker value used in new Zserv, in the byte location corresponding
|
||||
* the command value in the old zserv header. To allow old and new
|
||||
* Zserv headers to be distinguished from each other.
|
||||
@ -438,14 +382,6 @@ extern const char *zserv_command_string (unsigned int command);
|
||||
|
||||
#define strmatch(a,b) (!strcmp((a), (b)))
|
||||
|
||||
/* Error codes of zebra. */
|
||||
#define ZEBRA_ERR_NOERROR 0
|
||||
#define ZEBRA_ERR_RTEXIST -1
|
||||
#define ZEBRA_ERR_RTUNREACH -2
|
||||
#define ZEBRA_ERR_EPERM -3
|
||||
#define ZEBRA_ERR_RTNOEXIST -4
|
||||
#define ZEBRA_ERR_KERNEL -5
|
||||
|
||||
/* Zebra message flags */
|
||||
#define ZEBRA_FLAG_INTERNAL 0x01
|
||||
#define ZEBRA_FLAG_SELFROUTE 0x02
|
||||
|
@ -1367,7 +1367,8 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c
|
||||
if (uj) {
|
||||
json = json_object_new_object();
|
||||
} else {
|
||||
vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE);
|
||||
vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
|
||||
vty_out(vty, "%sInstalled Source Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
|
||||
@ -1379,9 +1380,6 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c
|
||||
struct interface *ifp_in;
|
||||
first_oif = 1;
|
||||
|
||||
if (!c_oil->installed)
|
||||
continue;
|
||||
|
||||
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str));
|
||||
pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str));
|
||||
ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
|
||||
@ -1426,7 +1424,8 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c
|
||||
json_object_object_add(json_source, in_ifname, json_ifp_in);
|
||||
}
|
||||
} else {
|
||||
vty_out(vty, "%-15s %-15s %-5s ",
|
||||
vty_out(vty, "%-9d %-15s %-15s %-7s ",
|
||||
c_oil->installed,
|
||||
src_str,
|
||||
grp_str,
|
||||
ifp_in->name);
|
||||
@ -1455,16 +1454,25 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c
|
||||
json_object_string_add(json_ifp_out, "group", grp_str);
|
||||
json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
|
||||
json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
|
||||
json_object_int_add(json_ifp_out, "installed", c_oil->installed);
|
||||
|
||||
json_object_object_add(json_ifp_in, out_ifname, json_ifp_out);
|
||||
} else {
|
||||
if (first_oif)
|
||||
{
|
||||
first_oif = 0;
|
||||
vty_out(vty, "%s", out_ifname);
|
||||
vty_out(vty, "%s(%c%c%c%c)", out_ifname,
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ');
|
||||
}
|
||||
else
|
||||
vty_out(vty, ",%s", out_ifname);
|
||||
vty_out(vty, ", %s(%c%c%c%c)", out_ifname,
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ',
|
||||
(c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' );
|
||||
}
|
||||
}
|
||||
|
||||
@ -2825,21 +2833,11 @@ DEFUN (show_ip_multicast,
|
||||
}
|
||||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, "Zclient update socket: ");
|
||||
if (qpim_zclient_update) {
|
||||
vty_out(vty, "%d failures=%d%s", qpim_zclient_update->sock,
|
||||
qpim_zclient_update->fail, VTY_NEWLINE);
|
||||
}
|
||||
else {
|
||||
vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
pim_zebra_zclient_update (vty);
|
||||
pim_zlookup_show_ip_multicast (vty);
|
||||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, "Current highest VifIndex: %d%s",
|
||||
qpim_mroute_oif_highest_vif_index,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, "Maximum highest VifIndex: %d%s",
|
||||
PIM_MAX_USABLE_VIFS,
|
||||
VTY_NEWLINE);
|
||||
@ -2970,6 +2968,9 @@ static void show_mroute(struct vty *vty, u_char uj)
|
||||
if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE)
|
||||
json_object_boolean_true_add(json_ifp_out, "protocolSource");
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR)
|
||||
json_object_boolean_true_add(json_ifp_out, "protocolInherited");
|
||||
|
||||
json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
|
||||
json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent);
|
||||
json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
|
||||
@ -2994,6 +2995,10 @@ static void show_mroute(struct vty *vty, u_char uj)
|
||||
strcpy(proto, "SRC");
|
||||
}
|
||||
|
||||
if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) {
|
||||
strcpy(proto, "STAR");
|
||||
}
|
||||
|
||||
vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
|
||||
src_str,
|
||||
grp_str,
|
||||
|
@ -44,12 +44,18 @@
|
||||
|
||||
struct interface *pim_regiface = NULL;
|
||||
struct list *pim_ifchannel_list = NULL;
|
||||
static int pim_iface_vif_index[MAXVIFS];
|
||||
|
||||
static void pim_if_igmp_join_del_all(struct interface *ifp);
|
||||
|
||||
void
|
||||
pim_if_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXVIFS; i++)
|
||||
pim_iface_vif_index[i] = 0;
|
||||
|
||||
vrf_iflist_create(VRF_DEFAULT);
|
||||
pim_ifchannel_list = list_new();
|
||||
pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
|
||||
@ -848,11 +854,10 @@ pim_find_primary_addr (struct interface *ifp)
|
||||
return addr;
|
||||
}
|
||||
|
||||
static int pim_iface_vif_index = 0;
|
||||
|
||||
static int
|
||||
pim_iface_next_vif_index (struct interface *ifp)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* The pimreg vif is always going to be in index 0
|
||||
* of the table.
|
||||
@ -860,8 +865,12 @@ pim_iface_next_vif_index (struct interface *ifp)
|
||||
if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
|
||||
return 0;
|
||||
|
||||
pim_iface_vif_index++;
|
||||
return pim_iface_vif_index;
|
||||
for (i = 1 ; i < MAXVIFS; i++)
|
||||
{
|
||||
if (pim_iface_vif_index[i] == 0)
|
||||
return i;
|
||||
}
|
||||
return MAXVIFS;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -884,7 +893,7 @@ int pim_if_add_vif(struct interface *ifp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ifp->ifindex < 1) {
|
||||
if (ifp->ifindex < 0) {
|
||||
zlog_warn("%s: ifindex=%d < 1 on interface %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
ifp->ifindex, ifp->name);
|
||||
@ -921,41 +930,13 @@ int pim_if_add_vif(struct interface *ifp)
|
||||
return -5;
|
||||
}
|
||||
|
||||
/*
|
||||
Update highest vif_index
|
||||
*/
|
||||
if (pim_ifp->mroute_vif_index != PIM_OIF_PIM_REGISTER_VIF &&
|
||||
pim_ifp->mroute_vif_index > qpim_mroute_oif_highest_vif_index) {
|
||||
qpim_mroute_oif_highest_vif_index = pim_ifp->mroute_vif_index;
|
||||
}
|
||||
|
||||
pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iflist_find_highest_vif_index()
|
||||
{
|
||||
struct listnode *ifnode;
|
||||
struct interface *ifp;
|
||||
struct pim_interface *pim_ifp;
|
||||
int highest_vif_index = -1;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
|
||||
pim_ifp = ifp->info;
|
||||
if (!pim_ifp)
|
||||
continue;
|
||||
|
||||
if (pim_ifp->mroute_vif_index > highest_vif_index) {
|
||||
highest_vif_index = pim_ifp->mroute_vif_index;
|
||||
}
|
||||
}
|
||||
|
||||
return highest_vif_index;
|
||||
}
|
||||
|
||||
int pim_if_del_vif(struct interface *ifp)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
int old_vif_index;
|
||||
|
||||
if (pim_ifp->mroute_vif_index < 1) {
|
||||
zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
|
||||
@ -970,18 +951,12 @@ int pim_if_del_vif(struct interface *ifp)
|
||||
}
|
||||
|
||||
/*
|
||||
Update highest vif_index
|
||||
Update vif_index
|
||||
*/
|
||||
|
||||
/* save old vif_index in order to compare with highest below */
|
||||
old_vif_index = pim_ifp->mroute_vif_index;
|
||||
pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0;
|
||||
|
||||
pim_ifp->mroute_vif_index = -1;
|
||||
|
||||
if (old_vif_index == qpim_mroute_oif_highest_vif_index) {
|
||||
qpim_mroute_oif_highest_vif_index = iflist_find_highest_vif_index();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,11 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
|
||||
if (ch->upstream->channel_oil)
|
||||
{
|
||||
pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
|
||||
if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
|
||||
mask = PIM_OIF_FLAG_PROTO_IGMP;
|
||||
|
||||
pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask);
|
||||
/*
|
||||
* Do we have any S,G's that are inheriting?
|
||||
* Nuke from on high too.
|
||||
@ -153,7 +157,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
struct listnode *up_node;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child))
|
||||
pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,15 +274,19 @@ void pim_ifchannel_ifjoin_switch(const char *caller,
|
||||
continue;
|
||||
|
||||
if (!pim_upstream_evaluate_join_desired (child))
|
||||
pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
{
|
||||
pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||
pim_upstream_update_join_desired (child);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the S,G has no if channel and the c_oil still
|
||||
* has output here then the *,G was supplying the implied
|
||||
* if channel. So remove it.
|
||||
* I think this is dead code now. is it?
|
||||
*/
|
||||
if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
|
||||
pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||
}
|
||||
}
|
||||
if (ch->ifjoin_state == PIM_IFJOIN_JOIN)
|
||||
@ -292,8 +300,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller,
|
||||
|
||||
if (pim_upstream_evaluate_join_desired (child))
|
||||
{
|
||||
pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
|
||||
pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
|
||||
pim_upstream_update_join_desired (child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -492,7 +500,7 @@ pim_ifchannel_add(struct interface *ifp,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch = XMALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch));
|
||||
ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch));
|
||||
if (!ch) {
|
||||
zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s",
|
||||
__PRETTY_FUNCTION__,
|
||||
@ -531,6 +539,7 @@ pim_ifchannel_add(struct interface *ifp,
|
||||
|
||||
/* Assert state */
|
||||
ch->t_ifassert_timer = NULL;
|
||||
ch->ifassert_state = PIM_IFASSERT_NOINFO;
|
||||
reset_ifassert_state(ch);
|
||||
if (pim_macro_ch_could_assert_eval(ch))
|
||||
PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags);
|
||||
@ -929,8 +938,9 @@ void pim_ifchannel_prune(struct interface *ifp,
|
||||
}
|
||||
}
|
||||
|
||||
void pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
struct prefix_sg *sg)
|
||||
int
|
||||
pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
struct prefix_sg *sg)
|
||||
{
|
||||
struct pim_ifchannel *ch;
|
||||
struct pim_interface *pim_ifp;
|
||||
@ -938,13 +948,13 @@ void pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
/* PIM enabled on interface? */
|
||||
pim_ifp = ifp->info;
|
||||
if (!pim_ifp)
|
||||
return;
|
||||
return 0;
|
||||
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
|
||||
if (!ch) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
|
||||
@ -964,11 +974,13 @@ void pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
|
||||
if (pim_upstream_evaluate_join_desired (child))
|
||||
{
|
||||
pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
@ -1008,7 +1020,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
up->sg_str, ifp->name, child->sg_str);
|
||||
|
||||
if (c_oil && !pim_upstream_evaluate_join_desired (child))
|
||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||
|
||||
/*
|
||||
* If the S,G has no if channel and the c_oil still
|
||||
@ -1016,7 +1028,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
* if channel. So remove it.
|
||||
*/
|
||||
if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
|
||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
|
||||
pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
|
||||
}
|
||||
}
|
||||
delete_on_noinfo(ch);
|
||||
|
@ -130,8 +130,8 @@ void pim_ifchannel_prune(struct interface *ifp,
|
||||
struct prefix_sg *sg,
|
||||
uint8_t source_flags,
|
||||
uint16_t holdtime);
|
||||
void pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
struct prefix_sg *sg);
|
||||
int pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
struct prefix_sg *sg);
|
||||
void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
struct prefix_sg *sg);
|
||||
|
||||
|
@ -41,8 +41,6 @@
|
||||
#include "pim_zlookup.h"
|
||||
|
||||
/* GLOBAL VARS */
|
||||
extern struct zebra_privs_t pimd_privs;
|
||||
|
||||
static struct thread *qpim_mroute_socket_reader = NULL;
|
||||
|
||||
static void mroute_read_on(void);
|
||||
@ -812,13 +810,10 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
|
||||
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
{
|
||||
struct prefix_sg sg;
|
||||
|
||||
sg.src = c_oil->oil.mfcc_origin;
|
||||
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
||||
|
||||
zlog_debug("%s(%s), Added Route: %s to mroute table",
|
||||
__PRETTY_FUNCTION__, name, pim_str_sg_dump(&sg));
|
||||
char buf[1000];
|
||||
zlog_debug("%s(%s), Added Route: %s",
|
||||
__PRETTY_FUNCTION__, name,
|
||||
pim_channel_oil_dump (c_oil, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
c_oil->installed = 1;
|
||||
@ -850,14 +845,12 @@ int pim_mroute_del (struct channel_oil *c_oil, const char *name)
|
||||
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
{
|
||||
struct prefix_sg sg;
|
||||
|
||||
sg.src = c_oil->oil.mfcc_origin;
|
||||
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
||||
|
||||
zlog_debug("%s(%s), Deleted Route: %s from mroute table",
|
||||
__PRETTY_FUNCTION__, name, pim_str_sg_dump(&sg));
|
||||
char buf[1000];
|
||||
zlog_debug("%s(%s), Deleted Route: %s",
|
||||
__PRETTY_FUNCTION__, name,
|
||||
pim_channel_oil_dump (c_oil, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
c_oil->installed = 0;
|
||||
|
||||
return 0;
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "pim_msdp.h"
|
||||
#include "pim_msdp_socket.h"
|
||||
|
||||
extern struct zebra_privs_t pimd_privs;
|
||||
|
||||
/* increase socket send buffer size */
|
||||
static void
|
||||
pim_msdp_update_sock_send_buffer_size (int fd)
|
||||
|
@ -36,6 +36,31 @@
|
||||
struct list *pim_channel_oil_list = NULL;
|
||||
struct hash *pim_channel_oil_hash = NULL;
|
||||
|
||||
char *
|
||||
pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size)
|
||||
{
|
||||
struct prefix_sg sg;
|
||||
int i;
|
||||
|
||||
memset (buf, 0, size);
|
||||
sg.src = c_oil->oil.mfcc_origin;
|
||||
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
||||
sprintf(buf, "%s IIF: %d, OIFS: ",
|
||||
pim_str_sg_dump (&sg), c_oil->oil.mfcc_parent);
|
||||
|
||||
for (i = 0 ; i < MAXVIFS ; i++)
|
||||
{
|
||||
if (c_oil->oil.mfcc_ttls[i] != 0)
|
||||
{
|
||||
char buf1[10];
|
||||
sprintf(buf1, "%d ", i);
|
||||
strcat(buf, buf1);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2)
|
||||
{
|
||||
@ -353,25 +378,26 @@ int pim_channel_add_oif(struct channel_oil *channel_oil,
|
||||
}
|
||||
|
||||
/* Allow other protocol to request subscription of same interface to
|
||||
channel (S,G) multiple times, by silently ignoring further
|
||||
requests */
|
||||
* channel (S,G), we need to note this information
|
||||
*/
|
||||
if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
|
||||
|
||||
channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec();
|
||||
channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
|
||||
/* Check the OIF really exists before returning, and only log
|
||||
warning otherwise */
|
||||
if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
{
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
|
||||
pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
|
||||
zlog_debug("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
proto_mask, oif->name, pim_ifp->mroute_vif_index,
|
||||
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
|
||||
source_str, group_str);
|
||||
}
|
||||
{
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
|
||||
pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
|
||||
zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
|
||||
__FILE__, __PRETTY_FUNCTION__,
|
||||
proto_mask, oif->name, pim_ifp->mroute_vif_index,
|
||||
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
|
||||
source_str, group_str);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -29,13 +29,16 @@
|
||||
* IGMP - Learned from IGMP
|
||||
* PIM - Learned from PIM
|
||||
* SOURCE - Learned from Source multicast packet received
|
||||
* STAR - Inherited
|
||||
*/
|
||||
#define PIM_OIF_FLAG_PROTO_IGMP (1 << 0)
|
||||
#define PIM_OIF_FLAG_PROTO_PIM (1 << 1)
|
||||
#define PIM_OIF_FLAG_PROTO_SOURCE (2 << 1)
|
||||
#define PIM_OIF_FLAG_PROTO_SOURCE (1 << 2)
|
||||
#define PIM_OIF_FLAG_PROTO_STAR (1 << 3)
|
||||
#define PIM_OIF_FLAG_PROTO_ANY (PIM_OIF_FLAG_PROTO_IGMP | \
|
||||
PIM_OIF_FLAG_PROTO_PIM | \
|
||||
PIM_OIF_FLAG_PROTO_SOURCE)
|
||||
PIM_OIF_FLAG_PROTO_SOURCE | \
|
||||
PIM_OIF_FLAG_PROTO_STAR)
|
||||
|
||||
/*
|
||||
* We need a pimreg vif id from the kernel.
|
||||
@ -45,8 +48,8 @@
|
||||
* Don't come running to me if this assumption is bad,
|
||||
* fix it.
|
||||
*/
|
||||
#define PIM_OIF_PIM_REGISTER_VIF (MAXVIFS - 1)
|
||||
#define PIM_MAX_USABLE_VIFS (MAXVIFS - 2)
|
||||
#define PIM_OIF_PIM_REGISTER_VIF 0
|
||||
#define PIM_MAX_USABLE_VIFS (MAXVIFS - 1)
|
||||
|
||||
|
||||
struct channel_counts
|
||||
@ -96,4 +99,6 @@ int pim_channel_del_oif (struct channel_oil *c_oil,
|
||||
uint32_t proto_mask);
|
||||
|
||||
int pim_channel_oil_empty (struct channel_oil *c_oil);
|
||||
|
||||
char *pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size);
|
||||
#endif /* PIM_OIL_H */
|
||||
|
@ -126,7 +126,8 @@ void
|
||||
pim_rp_free (void)
|
||||
{
|
||||
if (qpim_rp_list)
|
||||
list_free (qpim_rp_list);
|
||||
list_delete (qpim_rp_list);
|
||||
qpim_rp_list = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "pim_igmp_join.h"
|
||||
|
||||
/* GLOBAL VARS */
|
||||
extern struct zebra_privs_t pimd_privs;
|
||||
|
||||
int
|
||||
pim_socket_raw (int protocol)
|
||||
|
@ -1288,7 +1288,11 @@ pim_upstream_inherited_olist_decide (struct pim_upstream *up)
|
||||
|
||||
if (pim_upstream_evaluate_join_desired_interface (up, ch))
|
||||
{
|
||||
pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_PIM);
|
||||
int flag = PIM_OIF_FLAG_PROTO_PIM;
|
||||
|
||||
if (ch->sg.src.s_addr == INADDR_ANY && ch->upstream != up)
|
||||
flag = PIM_OIF_FLAG_PROTO_STAR;
|
||||
pim_channel_add_oif (up->channel_oil, ch->interface, flag);
|
||||
output_intf++;
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,8 @@
|
||||
#undef PIM_DEBUG_IFADDR_DUMP
|
||||
#define PIM_DEBUG_IFADDR_DUMP
|
||||
|
||||
static struct zclient *zclient = NULL;
|
||||
|
||||
static int fib_lookup_if_vif_index(struct in_addr addr);
|
||||
static int del_oif(struct channel_oil *channel_oil,
|
||||
struct interface *oif,
|
||||
@ -724,31 +726,31 @@ void pim_zebra_init(char *zebra_sock_path)
|
||||
#endif
|
||||
|
||||
/* Socket for receiving updates from Zebra daemon */
|
||||
qpim_zclient_update = zclient_new (master);
|
||||
zclient = zclient_new (master);
|
||||
|
||||
qpim_zclient_update->zebra_connected = pim_zebra_connected;
|
||||
qpim_zclient_update->router_id_update = pim_router_id_update_zebra;
|
||||
qpim_zclient_update->interface_add = pim_zebra_if_add;
|
||||
qpim_zclient_update->interface_delete = pim_zebra_if_del;
|
||||
qpim_zclient_update->interface_up = pim_zebra_if_state_up;
|
||||
qpim_zclient_update->interface_down = pim_zebra_if_state_down;
|
||||
qpim_zclient_update->interface_address_add = pim_zebra_if_address_add;
|
||||
qpim_zclient_update->interface_address_delete = pim_zebra_if_address_del;
|
||||
qpim_zclient_update->redistribute_route_ipv4_add = redist_read_ipv4_route;
|
||||
qpim_zclient_update->redistribute_route_ipv4_del = redist_read_ipv4_route;
|
||||
zclient->zebra_connected = pim_zebra_connected;
|
||||
zclient->router_id_update = pim_router_id_update_zebra;
|
||||
zclient->interface_add = pim_zebra_if_add;
|
||||
zclient->interface_delete = pim_zebra_if_del;
|
||||
zclient->interface_up = pim_zebra_if_state_up;
|
||||
zclient->interface_down = pim_zebra_if_state_down;
|
||||
zclient->interface_address_add = pim_zebra_if_address_add;
|
||||
zclient->interface_address_delete = pim_zebra_if_address_del;
|
||||
zclient->redistribute_route_ipv4_add = redist_read_ipv4_route;
|
||||
zclient->redistribute_route_ipv4_del = redist_read_ipv4_route;
|
||||
|
||||
zclient_init(qpim_zclient_update, ZEBRA_ROUTE_PIM, 0);
|
||||
zclient_init(zclient, ZEBRA_ROUTE_PIM, 0);
|
||||
if (PIM_DEBUG_PIM_TRACE) {
|
||||
zlog_info("zclient_init cleared redistribution request");
|
||||
}
|
||||
|
||||
zassert(qpim_zclient_update->redist_default == ZEBRA_ROUTE_PIM);
|
||||
zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
|
||||
|
||||
/* Request all redistribution */
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i == qpim_zclient_update->redist_default)
|
||||
if (i == zclient->redist_default)
|
||||
continue;
|
||||
vrf_bitmap_set (qpim_zclient_update->redist[AFI_IP][i], VRF_DEFAULT);;
|
||||
vrf_bitmap_set (zclient->redist[AFI_IP][i], VRF_DEFAULT);;
|
||||
if (PIM_DEBUG_PIM_TRACE) {
|
||||
zlog_debug("%s: requesting redistribution for %s (%i)",
|
||||
__PRETTY_FUNCTION__, zebra_route_string(i), i);
|
||||
@ -757,7 +759,7 @@ void pim_zebra_init(char *zebra_sock_path)
|
||||
|
||||
/* Request default information */
|
||||
zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
||||
qpim_zclient_update, VRF_DEFAULT);
|
||||
zclient, VRF_DEFAULT);
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE) {
|
||||
zlog_info("%s: requesting default information redistribution",
|
||||
@ -1095,7 +1097,13 @@ void igmp_source_forward_start(struct igmp_source *source)
|
||||
Feed IGMPv3-gathered local membership information into PIM
|
||||
per-interface (S,G) state.
|
||||
*/
|
||||
pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg);
|
||||
if (!pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg))
|
||||
{
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
zlog_warn ("%s: Failure to add local membership for %s",
|
||||
__PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
|
||||
return;
|
||||
}
|
||||
|
||||
IGMP_SOURCE_DO_FORWARDING(source->source_flags);
|
||||
}
|
||||
@ -1165,6 +1173,7 @@ void igmp_source_forward_stop(struct igmp_source *source)
|
||||
void pim_forward_start(struct pim_ifchannel *ch)
|
||||
{
|
||||
struct pim_upstream *up = ch->upstream;
|
||||
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE) {
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
@ -1204,9 +1213,10 @@ void pim_forward_start(struct pim_ifchannel *ch)
|
||||
}
|
||||
}
|
||||
|
||||
pim_channel_add_oif(up->channel_oil,
|
||||
ch->interface,
|
||||
PIM_OIF_FLAG_PROTO_PIM);
|
||||
if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
|
||||
mask = PIM_OIF_FLAG_PROTO_IGMP;
|
||||
|
||||
pim_channel_add_oif(up->channel_oil, ch->interface, mask);
|
||||
}
|
||||
|
||||
void pim_forward_stop(struct pim_ifchannel *ch)
|
||||
@ -1232,3 +1242,17 @@ void pim_forward_stop(struct pim_ifchannel *ch)
|
||||
ch->interface,
|
||||
PIM_OIF_FLAG_PROTO_PIM);
|
||||
}
|
||||
|
||||
void
|
||||
pim_zebra_zclient_update (struct vty *vty)
|
||||
{
|
||||
vty_out(vty, "Zclient update socket: ");
|
||||
|
||||
if (zclient) {
|
||||
vty_out(vty, "%d failures=%d%s", zclient->sock,
|
||||
zclient->fail, VTY_NEWLINE);
|
||||
}
|
||||
else {
|
||||
vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "pim_ifchannel.h"
|
||||
|
||||
void pim_zebra_init(char *zebra_sock_path);
|
||||
void pim_zebra_zclient_update (struct vty *vty);
|
||||
|
||||
void pim_scan_individual_oil (struct channel_oil *c_oil);
|
||||
void pim_scan_oil(void);
|
||||
|
@ -120,6 +120,13 @@ static void zclient_lookup_failed(struct zclient *zlookup)
|
||||
zclient_lookup_reconnect(zlookup);
|
||||
}
|
||||
|
||||
void
|
||||
zclient_lookup_free (void)
|
||||
{
|
||||
zclient_free (zlookup);
|
||||
zlookup = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
zclient_lookup_new (void)
|
||||
{
|
||||
@ -131,9 +138,7 @@ zclient_lookup_new (void)
|
||||
}
|
||||
|
||||
zlookup->sock = -1;
|
||||
zlookup->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
zlookup->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
zlookup->t_connect = 0;
|
||||
zlookup->t_connect = NULL;
|
||||
|
||||
zclient_lookup_sched_now(zlookup);
|
||||
|
||||
|
@ -35,6 +35,7 @@ struct pim_zlookup_nexthop {
|
||||
};
|
||||
|
||||
void zclient_lookup_new (void);
|
||||
void zclient_lookup_free (void);
|
||||
|
||||
int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[],
|
||||
const int tab_size,
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "pim_ssmpingd.h"
|
||||
#include "pim_static.h"
|
||||
#include "pim_rp.h"
|
||||
#include "pim_zlookup.h"
|
||||
|
||||
const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS;
|
||||
const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS;
|
||||
@ -49,9 +50,7 @@ struct thread_master *master = NULL;
|
||||
uint32_t qpim_debugs = 0;
|
||||
int qpim_mroute_socket_fd = -1;
|
||||
int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */
|
||||
int qpim_mroute_oif_highest_vif_index = -1;
|
||||
int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
|
||||
struct zclient *qpim_zclient_update = NULL;
|
||||
struct pim_assert_metric qpim_infinite_assert_metric;
|
||||
long qpim_rpf_cache_refresh_delay_msec = 50;
|
||||
struct thread *qpim_rpf_cache_refresher = NULL;
|
||||
@ -91,6 +90,10 @@ static void pim_free()
|
||||
pim_rp_free ();
|
||||
|
||||
pim_route_map_terminate();
|
||||
|
||||
zclient_lookup_free ();
|
||||
|
||||
zprivs_terminate(&pimd_privs);
|
||||
}
|
||||
|
||||
void pim_init()
|
||||
@ -122,7 +125,6 @@ void pim_init()
|
||||
qpim_static_route_list->del = (void (*)(void *)) pim_static_route_free;
|
||||
|
||||
qpim_mroute_socket_fd = -1; /* mark mroute as disabled */
|
||||
qpim_mroute_oif_highest_vif_index = -1;
|
||||
|
||||
qpim_inaddr_any.s_addr = PIM_NET_INADDR_ANY;
|
||||
|
||||
|
@ -96,13 +96,12 @@ const char *const PIM_ALL_PIM_ROUTERS;
|
||||
const char *const PIM_ALL_IGMP_ROUTERS;
|
||||
|
||||
extern struct thread_master *master;
|
||||
extern struct zebra_privs_t pimd_privs;
|
||||
uint32_t qpim_debugs;
|
||||
int qpim_mroute_socket_fd;
|
||||
int64_t qpim_mroute_socket_creation; /* timestamp of creation */
|
||||
int qpim_mroute_oif_highest_vif_index;
|
||||
struct in_addr qpim_all_pim_routers_addr;
|
||||
int qpim_t_periodic; /* Period between Join/Prune Messages */
|
||||
struct zclient *qpim_zclient_update;
|
||||
struct pim_assert_metric qpim_infinite_assert_metric;
|
||||
long qpim_rpf_cache_refresh_delay_msec;
|
||||
struct thread *qpim_rpf_cache_refresher;
|
||||
|
@ -23,6 +23,14 @@
|
||||
#ifndef __ZEBRA_KERNEL_SOCKET_H
|
||||
#define __ZEBRA_KERNEL_SOCKET_H
|
||||
|
||||
/* Error codes of zebra. */
|
||||
#define ZEBRA_ERR_NOERROR 0
|
||||
#define ZEBRA_ERR_RTEXIST -1
|
||||
#define ZEBRA_ERR_RTUNREACH -2
|
||||
#define ZEBRA_ERR_EPERM -3
|
||||
#define ZEBRA_ERR_RTNOEXIST -4
|
||||
#define ZEBRA_ERR_KERNEL -5
|
||||
|
||||
extern void rtm_read (struct rt_msghdr *);
|
||||
extern int ifam_read (struct ifa_msghdr *);
|
||||
extern int ifm_read (struct if_msghdr *);
|
||||
|
@ -349,10 +349,10 @@ extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *,
|
||||
struct rib *);
|
||||
|
||||
extern int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
u_short instance, int flags, struct prefix *p,
|
||||
union g_addr *gate, ifindex_t ifindex,
|
||||
u_int32_t table_id);
|
||||
extern void rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
u_short instance, int flags, struct prefix *p,
|
||||
union g_addr *gate, ifindex_t ifindex,
|
||||
u_int32_t table_id);
|
||||
|
||||
extern struct rib *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *,
|
||||
struct route_node **rn_out);
|
||||
|
@ -347,10 +347,10 @@ nexthop_has_fib_child(struct nexthop *nexthop)
|
||||
/* If force flag is not set, do not modify falgs at all for uninstall
|
||||
the route from FIB. */
|
||||
static int
|
||||
nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
struct route_node *top)
|
||||
nexthop_active (afi_t afi, struct rib *rib, struct nexthop *nexthop, int set,
|
||||
struct route_node *top)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix p;
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct rib *match;
|
||||
@ -360,7 +360,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
int recursing = 0;
|
||||
struct interface *ifp;
|
||||
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4)
|
||||
if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6)
|
||||
nexthop->ifindex = 0;
|
||||
|
||||
if (set)
|
||||
@ -398,13 +398,25 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
}
|
||||
|
||||
/* Make lookup prefix. */
|
||||
memset (&p, 0, sizeof (struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
p.prefix = nexthop->gate.ipv4;
|
||||
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
switch (afi)
|
||||
{
|
||||
case AFI_IP:
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
p.u.prefix4 = nexthop->gate.ipv4;
|
||||
break;
|
||||
case AFI_IP6:
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_PREFIXLEN;
|
||||
p.u.prefix6 = nexthop->gate.ipv6;
|
||||
break;
|
||||
default:
|
||||
assert (afi != AFI_IP && afi != AFI_IP6);
|
||||
break;
|
||||
}
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id);
|
||||
table = zebra_vrf_table (afi, SAFI_UNICAST, rib->vrf_id);
|
||||
if (! table)
|
||||
return 0;
|
||||
|
||||
@ -457,9 +469,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
{
|
||||
/* Directly point connected route. */
|
||||
newhop = match->nexthop;
|
||||
if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
|
||||
nexthop->ifindex = newhop->ifindex;
|
||||
|
||||
if (newhop)
|
||||
{
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
|
||||
nexthop->type == NEXTHOP_TYPE_IPV6)
|
||||
nexthop->ifindex = newhop->ifindex;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
|
||||
@ -491,6 +506,18 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
}
|
||||
}
|
||||
if (newhop->type == NEXTHOP_TYPE_IPV6
|
||||
|| newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||
{
|
||||
resolved_hop->type = newhop->type;
|
||||
resolved_hop->gate.ipv6 = newhop->gate.ipv6;
|
||||
|
||||
if (newhop->ifindex)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the resolving route is an interface route,
|
||||
* it means the gateway we are looking up is connected
|
||||
@ -503,8 +530,16 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
if (newhop->type == NEXTHOP_TYPE_IFINDEX)
|
||||
{
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
|
||||
if (afi == AFI_IP)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
|
||||
}
|
||||
else if (afi == AFI_IP6)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
|
||||
}
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
|
||||
@ -541,6 +576,18 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
}
|
||||
}
|
||||
if (newhop->type == NEXTHOP_TYPE_IPV6
|
||||
|| newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||
{
|
||||
resolved_hop->type = newhop->type;
|
||||
resolved_hop->gate.ipv6 = newhop->gate.ipv6;
|
||||
|
||||
if (newhop->ifindex)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the resolving route is an interface route,
|
||||
* it means the gateway we are looking up is connected
|
||||
@ -554,8 +601,16 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
if (newhop->type == NEXTHOP_TYPE_IFINDEX)
|
||||
{
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
|
||||
if (afi == AFI_IP)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
|
||||
}
|
||||
else if (afi == AFI_IP6)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
|
||||
}
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
|
||||
@ -576,193 +631,6 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If force flag is not set, do not modify falgs at all for uninstall
|
||||
the route from FIB. */
|
||||
static int
|
||||
nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
|
||||
struct route_node *top)
|
||||
{
|
||||
struct prefix_ipv6 p;
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct rib *match;
|
||||
int resolved;
|
||||
struct nexthop *newhop, *tnewhop;
|
||||
int recursing = 0;
|
||||
struct nexthop *resolved_hop;
|
||||
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV6)
|
||||
nexthop->ifindex = 0;
|
||||
|
||||
if (set)
|
||||
{
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
|
||||
zebra_deregister_rnh_static_nexthops (rib->vrf_id, nexthop->resolved, top);
|
||||
nexthops_free(nexthop->resolved);
|
||||
nexthop->resolved = NULL;
|
||||
}
|
||||
|
||||
/* Skip nexthops that have been filtered out due to route-map */
|
||||
/* The nexthops are specific to this route and so the same */
|
||||
/* nexthop for a different route may not have this flag set */
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED))
|
||||
return 0;
|
||||
|
||||
/* Make lookup prefix. */
|
||||
memset (&p, 0, sizeof (struct prefix_ipv6));
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_PREFIXLEN;
|
||||
p.prefix = nexthop->gate.ipv6;
|
||||
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
|
||||
if (! table)
|
||||
return 0;
|
||||
|
||||
rn = route_node_match (table, (struct prefix *) &p);
|
||||
while (rn)
|
||||
{
|
||||
route_unlock_node (rn);
|
||||
|
||||
/* If lookup self prefix return immediately. */
|
||||
if (rn == top)
|
||||
return 0;
|
||||
|
||||
/* Pick up selected route. */
|
||||
/* However, do not resolve over default route unless explicitly allowed. */
|
||||
if (is_default_prefix (&rn->p) &&
|
||||
!nh_resolve_via_default (p.family))
|
||||
return 0;
|
||||
|
||||
RNODE_FOREACH_RIB (rn, match)
|
||||
{
|
||||
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
|
||||
continue;
|
||||
if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If there is no selected route or matched route is EGP, go up
|
||||
tree. */
|
||||
if (! match)
|
||||
{
|
||||
do {
|
||||
rn = rn->parent;
|
||||
} while (rn && rn->info == NULL);
|
||||
if (rn)
|
||||
route_lock_node (rn);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the longest prefix match for the nexthop yields
|
||||
* a blackhole, mark it as inactive. */
|
||||
if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
|
||||
|| CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
|
||||
return 0;
|
||||
|
||||
if (match->type == ZEBRA_ROUTE_CONNECT)
|
||||
{
|
||||
/* Directly point connected route. */
|
||||
newhop = match->nexthop;
|
||||
|
||||
if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
|
||||
nexthop->ifindex = newhop->ifindex;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
|
||||
{
|
||||
resolved = 0;
|
||||
for (newhop = match->nexthop; newhop; newhop = newhop->next)
|
||||
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
|
||||
&& ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
|
||||
SET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
|
||||
|
||||
resolved_hop = nexthop_new();
|
||||
SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
/* See nexthop_active_ipv4 for a description how the
|
||||
* resolved nexthop is constructed. */
|
||||
if (newhop->type == NEXTHOP_TYPE_IPV6
|
||||
|| newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||
{
|
||||
resolved_hop->type = newhop->type;
|
||||
resolved_hop->gate.ipv6 = newhop->gate.ipv6;
|
||||
|
||||
if (newhop->ifindex)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
if (newhop->type == NEXTHOP_TYPE_IFINDEX)
|
||||
{
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
|
||||
nexthop_add(&nexthop->resolved, resolved_hop);
|
||||
}
|
||||
resolved = 1;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
else if (rib->type == ZEBRA_ROUTE_STATIC)
|
||||
{
|
||||
resolved = 0;
|
||||
for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
|
||||
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
|
||||
|
||||
resolved_hop = nexthop_new();
|
||||
SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
/* See nexthop_active_ipv4 for a description how the
|
||||
* resolved nexthop is constructed. */
|
||||
if (newhop->type == NEXTHOP_TYPE_IPV6
|
||||
|| newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||
{
|
||||
resolved_hop->type = newhop->type;
|
||||
resolved_hop->gate.ipv6 = newhop->gate.ipv6;
|
||||
|
||||
if (newhop->ifindex)
|
||||
{
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
if (newhop->type == NEXTHOP_TYPE_IFINDEX)
|
||||
{
|
||||
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
|
||||
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
|
||||
resolved_hop->ifindex = newhop->ifindex;
|
||||
}
|
||||
|
||||
nexthop_add(&nexthop->resolved, resolved_hop);
|
||||
}
|
||||
resolved = 1;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rib *
|
||||
rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id,
|
||||
union g_addr *addr, struct route_node **rn_out)
|
||||
@ -1075,14 +943,14 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
family = AFI_IP;
|
||||
if (nexthop_active_ipv4 (rib, nexthop, set, rn))
|
||||
if (nexthop_active (AFI_IP, rib, nexthop, set, rn))
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
family = AFI_IP6;
|
||||
if (nexthop_active_ipv6 (rib, nexthop, set, rn))
|
||||
if (nexthop_active (AFI_IP6, rib, nexthop, set, rn))
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
@ -1101,7 +969,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nexthop_active_ipv6 (rib, nexthop, set, rn))
|
||||
if (nexthop_active (AFI_IP6, rib, nexthop, set, rn))
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
@ -1802,181 +1670,6 @@ rib_process (struct route_node *rn)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (select && select == fib)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p",
|
||||
(void *)select, (void *)fib);
|
||||
if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED))
|
||||
{
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
zfpm_trigger_update (rn, "updating existing route");
|
||||
|
||||
/* Set real nexthop. */
|
||||
/* Need to check if any NHs are active to clear the
|
||||
* the selected flag
|
||||
*/
|
||||
if (nexthop_active_update (rn, select, 1))
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d)",
|
||||
vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
|
||||
if (! RIB_SYSTEM_ROUTE (select))
|
||||
{
|
||||
/* Clear FIB flag if performing a replace, will get set again
|
||||
* as part of install.
|
||||
*/
|
||||
for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||
rib_install_kernel (rn, select, 1);
|
||||
}
|
||||
|
||||
/* assuming that the receiver knows how to dedup */
|
||||
redistribute_update (&rn->p, select, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) "
|
||||
"- nexthop inactive",
|
||||
vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
|
||||
|
||||
/* Withdraw unreachable redistribute route */
|
||||
redistribute_delete(&rn->p, select);
|
||||
|
||||
/* Do the uninstall here, if not done earlier. */
|
||||
if (! RIB_SYSTEM_ROUTE (select))
|
||||
rib_uninstall_kernel (rn, select);
|
||||
UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
|
||||
}
|
||||
UNSET_FLAG (select->status, RIB_ENTRY_CHANGED);
|
||||
}
|
||||
else if (! RIB_SYSTEM_ROUTE (select))
|
||||
{
|
||||
/* Housekeeping code to deal with
|
||||
race conditions in kernel with linux
|
||||
netlink reporting interface up before IPv4 or IPv6 protocol
|
||||
is ready to add routes.
|
||||
This makes sure the routes are IN the kernel.
|
||||
*/
|
||||
|
||||
for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing))
|
||||
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
|
||||
{
|
||||
installed = 1;
|
||||
break;
|
||||
}
|
||||
if (! installed)
|
||||
rib_install_kernel (rn, select, 0);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* At this point we either haven't found the best RIB entry or it is
|
||||
* different from what we currently intend to flag with SELECTED. In both
|
||||
* cases, if a RIB block is present in FIB, it should be withdrawn.
|
||||
*/
|
||||
if (fib)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
rnode_debug (rn, vrf_id, "Removing existing route, fib %p", (void *)fib);
|
||||
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
zfpm_trigger_update (rn, "removing existing route");
|
||||
|
||||
/* If there's no route to replace this with, withdraw redistribute and
|
||||
* uninstall from kernel.
|
||||
*/
|
||||
if (!select)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d)",
|
||||
vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type);
|
||||
|
||||
redistribute_delete(&rn->p, fib);
|
||||
if (! RIB_SYSTEM_ROUTE (fib))
|
||||
rib_uninstall_kernel (rn, fib);
|
||||
}
|
||||
|
||||
UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
|
||||
|
||||
/* Set real nexthop. */
|
||||
nexthop_active_update (rn, fib, 1);
|
||||
UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED);
|
||||
}
|
||||
|
||||
/* Regardless of some RIB entry being SELECTED or not before, now we can
|
||||
* tell, that if a new winner exists, FIB is still not updated with this
|
||||
* data, but ready to be.
|
||||
*/
|
||||
if (select)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
rnode_debug (rn, "Adding route, select %p", (void *)select);
|
||||
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
zfpm_trigger_update (rn, "new route selected");
|
||||
|
||||
/* Set real nexthop. */
|
||||
if (nexthop_active_update (rn, select, 1))
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
{
|
||||
if (fib)
|
||||
zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d) "
|
||||
"old %p (type %d)", vrf_id, buf, rn->p.prefixlen, rn,
|
||||
select, select->type, fib, fib->type);
|
||||
else
|
||||
zlog_debug ("%u:%s/%d: Adding route rn %p, rib %p (type %d)",
|
||||
vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
|
||||
}
|
||||
|
||||
if (! RIB_SYSTEM_ROUTE (select))
|
||||
{
|
||||
/* Clear FIB flag if performing a replace, will get set again
|
||||
* as part of install.
|
||||
*/
|
||||
if (fib)
|
||||
{
|
||||
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
|
||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||
}
|
||||
rib_install_kernel (rn, select, fib? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Uninstall prior route here, if needed. */
|
||||
if (fib && !RIB_SYSTEM_ROUTE (fib))
|
||||
rib_uninstall_kernel (rn, fib);
|
||||
}
|
||||
|
||||
SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
|
||||
/* Unconditionally announce, this part is exercised by new routes */
|
||||
/* If we cannot add, for example route added is learnt by the */
|
||||
/* protocol we're trying to redistribute to, delete the redist */
|
||||
/* This is notified by setting the is_update to 1 */
|
||||
redistribute_update (&rn->p, select, fib);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Uninstall prior route here and do redist delete, if needed. */
|
||||
if (fib)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) "
|
||||
"- nexthop inactive",
|
||||
vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE (fib))
|
||||
rib_uninstall_kernel (rn, fib);
|
||||
redistribute_delete(&rn->p, fib);
|
||||
}
|
||||
}
|
||||
UNSET_FLAG(select->status, RIB_ENTRY_CHANGED);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Remove all RIB entries queued for removal */
|
||||
RNODE_FOREACH_RIB_SAFE (rn, rib, next)
|
||||
{
|
||||
@ -2672,7 +2365,7 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
int flags, struct prefix *p, union g_addr *gate, ifindex_t ifindex,
|
||||
u_int32_t table_id)
|
||||
@ -2690,7 +2383,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id);
|
||||
if (! table)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* Apply mask. */
|
||||
apply_mask (p);
|
||||
@ -2702,7 +2395,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug ("%u:%s: doesn't exist in rib",
|
||||
vrf_id, prefix2str (p, buf1, sizeof(buf1)));
|
||||
return ZEBRA_ERR_RTNOEXIST;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Lookup same type route. */
|
||||
@ -2728,7 +2421,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
rib->refcnt--;
|
||||
route_unlock_node (rn);
|
||||
route_unlock_node (rn);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
same = rib;
|
||||
break;
|
||||
@ -2799,7 +2492,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
type);
|
||||
}
|
||||
route_unlock_node (rn);
|
||||
return ZEBRA_ERR_RTNOEXIST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2807,7 +2500,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
rib_delnode (rn, same);
|
||||
|
||||
route_unlock_node (rn);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -878,6 +878,7 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr
|
||||
}
|
||||
if (rib)
|
||||
{
|
||||
stream_putc (s, rib->distance);
|
||||
stream_putl (s, rib->metric);
|
||||
num = 0;
|
||||
nump = stream_get_endp(s);
|
||||
@ -917,8 +918,9 @@ send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vr
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_putl (s, 0);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, 0); // distance
|
||||
stream_putl (s, 0); // metric
|
||||
stream_putc (s, 0); // nexthops
|
||||
}
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user