summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_nht.c1
-rw-r--r--lib/log.c1
-rw-r--r--lib/zclient.h56
-rw-r--r--lib/zebra.h64
-rw-r--r--pimd/pim_cmd.c41
-rw-r--r--pimd/pim_iface.c59
-rw-r--r--pimd/pim_ifchannel.c42
-rw-r--r--pimd/pim_ifchannel.h4
-rw-r--r--pimd/pim_mroute.c25
-rw-r--r--pimd/pim_msdp_socket.c2
-rw-r--r--pimd/pim_oil.c54
-rw-r--r--pimd/pim_oil.h13
-rw-r--r--pimd/pim_rp.c3
-rw-r--r--pimd/pim_sock.c1
-rw-r--r--pimd/pim_upstream.c6
-rw-r--r--pimd/pim_zebra.c68
-rw-r--r--pimd/pim_zebra.h1
-rw-r--r--pimd/pim_zlookup.c11
-rw-r--r--pimd/pim_zlookup.h1
-rw-r--r--pimd/pimd.c8
-rw-r--r--pimd/pimd.h3
-rw-r--r--zebra/kernel_socket.h8
-rw-r--r--zebra/rib.h8
-rw-r--r--zebra/zebra_rib.c463
-rw-r--r--zebra/zebra_rnh.c6
25 files changed, 348 insertions, 601 deletions
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 057e2ace7..aa752280c 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -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);
diff --git a/lib/log.c b/lib/log.c
index b8e505f34..a421f6044 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -24,6 +24,7 @@
#include <zebra.h>
+#include "zclient.h"
#include "log.h"
#include "memory.h"
#include "command.h"
diff --git a/lib/zclient.h b/lib/zclient.h
index ccb7b0509..83b932f20 100644
--- a/lib/zclient.h
+++ b/lib/zclient.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;
diff --git a/lib/zebra.h b/lib/zebra.h
index bb43d062b..19a26b523 100644
--- a/lib/zebra.h
+++ b/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
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 7e60232ba..7e85253f9 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -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,
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index cc4f4f3dc..7f64c9d5f 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -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;
}
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 07318791e..f0e4a3a68 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -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);
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index bfe632135..a3dc0e9d8 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -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);
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index dfd22b702..bd9a1c460 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -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;
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index bc9720f1f..805e812ca 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -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)
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 0cebe4735..4c5eff488 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -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;
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 143cfb794..e90cd5fc1 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -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 */
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index ba464e98c..dc19002a4 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -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;
}
/*
diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c
index eda81c657..11cd61b59 100644
--- a/pimd/pim_sock.c
+++ b/pimd/pim_sock.c
@@ -42,7 +42,6 @@
#include "pim_igmp_join.h"
/* GLOBAL VARS */
-extern struct zebra_privs_t pimd_privs;
int
pim_socket_raw (int protocol)
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index fbb7d84a2..4ae49c0fd 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -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++;
}
}
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index b21da624d..1bb4852c6 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -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);
-
- 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_init(qpim_zclient_update, ZEBRA_ROUTE_PIM, 0);
+ zclient = zclient_new (master);
+
+ 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(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);
+ }
+}
diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h
index 0c302efbd..476185def 100644
--- a/pimd/pim_zebra.h
+++ b/pimd/pim_zebra.h
@@ -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);
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 61e3e2726..e1a8e820b 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -121,6 +121,13 @@ static void zclient_lookup_failed(struct zclient *zlookup)
}
void
+zclient_lookup_free (void)
+{
+ zclient_free (zlookup);
+ zlookup = NULL;
+}
+
+void
zclient_lookup_new (void)
{
zlookup = zclient_new (master);
@@ -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);
diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h
index d8e7ff9e0..34b1434c6 100644
--- a/pimd/pim_zlookup.h
+++ b/pimd/pim_zlookup.h
@@ -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,
diff --git a/pimd/pimd.c b/pimd/pimd.c
index e8960916a..2316cd08f 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -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;
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 20cf3c2dd..1f8dcdfb2 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -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;
diff --git a/zebra/kernel_socket.h b/zebra/kernel_socket.h
index 18d69343a..04e305431 100644
--- a/zebra/kernel_socket.h
+++ b/zebra/kernel_socket.h
@@ -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 *);
diff --git a/zebra/rib.h b/zebra/rib.h
index d80ea6cbd..99903769a 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -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);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 59893b1a0..c1c1f897a 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -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,151 +576,6 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
}
}
-
- /* If the resolving route is an interface route,
- * it means the gateway we are looking up is connected
- * to that interface. (The actual network is _not_ onlink).
- * Therefore, the resolved route should have the original
- * gateway as nexthop as it is directly connected.
- *
- * On Linux, we have to set the onlink netlink flag because
- * otherwise, the kernel won't accept the route.
- */
- 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;
- resolved_hop->ifindex = newhop->ifindex;
- }
-
- nexthop_add(&nexthop->resolved, resolved_hop);
- }
- resolved = 1;
- }
- if (resolved && set)
- rib->nexthop_mtu = match->mtu;
- return resolved;
- }
- else
- {
- return 0;
- }
- }
- }
- 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)
{
@@ -699,59 +589,37 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
}
}
+ /* If the resolving route is an interface route,
+ * it means the gateway we are looking up is connected
+ * to that interface. (The actual network is _not_ onlink).
+ * Therefore, the resolved route should have the original
+ * gateway as nexthop as it is directly connected.
+ *
+ * On Linux, we have to set the onlink netlink flag because
+ * otherwise, the kernel won't accept the route.
+ */
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->flags |= NEXTHOP_FLAG_ONLINK;
+ if (afi == AFI_IP)
{
- resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
- resolved_hop->ifindex = newhop->ifindex;
+ resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
}
- }
-
- if (newhop->type == NEXTHOP_TYPE_IFINDEX)
- {
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+ else if (afi == AFI_IP6)
+ {
resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
- resolved_hop->ifindex = newhop->ifindex;
+ }
+ resolved_hop->ifindex = newhop->ifindex;
}
nexthop_add(&nexthop->resolved, resolved_hop);
}
resolved = 1;
}
+ if (resolved && set)
+ rib->nexthop_mtu = match->mtu;
return resolved;
}
else
@@ -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;
}
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 182cfe552..b180930a0 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -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));