Merge branch 'frr/pull/133' ("Pim cleanup")

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2017-01-31 15:26:07 +01:00
commit 26df3a33ae
25 changed files with 349 additions and 602 deletions

View File

@ -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);

View File

@ -24,6 +24,7 @@
#include <zebra.h>
#include "zclient.h"
#include "log.h"
#include "memory.h"
#include "command.h"

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}
/*

View File

@ -42,7 +42,6 @@
#include "pim_igmp_join.h"
/* GLOBAL VARS */
extern struct zebra_privs_t pimd_privs;
int
pim_socket_raw (int protocol)

View File

@ -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++;
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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 *);

View File

@ -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);

View File

@ -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;
}

View File

@ -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));