diff options
-rw-r--r-- | bgpd/bgp_nht.c | 1 | ||||
-rw-r--r-- | lib/log.c | 1 | ||||
-rw-r--r-- | lib/zclient.h | 56 | ||||
-rw-r--r-- | lib/zebra.h | 64 | ||||
-rw-r--r-- | pimd/pim_cmd.c | 41 | ||||
-rw-r--r-- | pimd/pim_iface.c | 59 | ||||
-rw-r--r-- | pimd/pim_ifchannel.c | 42 | ||||
-rw-r--r-- | pimd/pim_ifchannel.h | 4 | ||||
-rw-r--r-- | pimd/pim_mroute.c | 25 | ||||
-rw-r--r-- | pimd/pim_msdp_socket.c | 2 | ||||
-rw-r--r-- | pimd/pim_oil.c | 54 | ||||
-rw-r--r-- | pimd/pim_oil.h | 13 | ||||
-rw-r--r-- | pimd/pim_rp.c | 3 | ||||
-rw-r--r-- | pimd/pim_sock.c | 1 | ||||
-rw-r--r-- | pimd/pim_upstream.c | 6 | ||||
-rw-r--r-- | pimd/pim_zebra.c | 68 | ||||
-rw-r--r-- | pimd/pim_zebra.h | 1 | ||||
-rw-r--r-- | pimd/pim_zlookup.c | 11 | ||||
-rw-r--r-- | pimd/pim_zlookup.h | 1 | ||||
-rw-r--r-- | pimd/pimd.c | 8 | ||||
-rw-r--r-- | pimd/pimd.h | 3 | ||||
-rw-r--r-- | zebra/kernel_socket.h | 8 | ||||
-rw-r--r-- | zebra/rib.h | 8 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 463 | ||||
-rw-r--r-- | zebra/zebra_rnh.c | 6 |
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); @@ -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)); |