diff options
Diffstat (limited to 'pimd/pim_static.c')
-rw-r--r-- | pimd/pim_static.c | 598 |
1 files changed, 309 insertions, 289 deletions
diff --git a/pimd/pim_static.c b/pimd/pim_static.c index d373581fe..7c9aca47a 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -34,317 +34,337 @@ void pim_static_route_free(struct static_route *s_route) { - XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); + XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); } -static struct static_route * static_route_alloc() +static struct static_route *static_route_alloc() { - struct static_route *s_route; - - s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); - if (!s_route) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); - return 0; - } - return s_route; + struct static_route *s_route; + + s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); + if (!s_route) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); + return 0; + } + return s_route; } -static struct static_route *static_route_new(unsigned int iif, - unsigned int oif, - struct in_addr group, - struct in_addr source) +static struct static_route *static_route_new(unsigned int iif, unsigned int oif, + struct in_addr group, + struct in_addr source) { - struct static_route * s_route; - s_route = static_route_alloc(); - if (!s_route) { - return 0; - } - - s_route->group = group; - s_route->source = source; - s_route->iif = iif; - s_route->oif_ttls[oif] = 1; - s_route->c_oil.oil_ref_count = 1; - s_route->c_oil.oil.mfcc_origin = source; - s_route->c_oil.oil.mfcc_mcastgrp = group; - s_route->c_oil.oil.mfcc_parent = iif; - s_route->c_oil.oil.mfcc_ttls[oif] = 1; - s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); - - return s_route; + struct static_route *s_route; + s_route = static_route_alloc(); + if (!s_route) { + return 0; + } + + s_route->group = group; + s_route->source = source; + s_route->iif = iif; + s_route->oif_ttls[oif] = 1; + s_route->c_oil.oil_ref_count = 1; + s_route->c_oil.oil.mfcc_origin = source; + s_route->c_oil.oil.mfcc_mcastgrp = group; + s_route->c_oil.oil.mfcc_parent = iif; + s_route->c_oil.oil.mfcc_ttls[oif] = 1; + s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); + + return s_route; } -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_add(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct static_route *s_route = NULL; - struct static_route *original_s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : NULL; - struct pim_interface *pim_oif = oif ? oif->info : NULL; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } + struct listnode *node = NULL; + struct static_route *s_route = NULL; + struct static_route *original_s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : NULL; + struct pim_interface *pim_oif = oif ? oif->info : NULL; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } #ifdef PIM_ENFORCE_LOOPFREE_MFC - if (iif_index == oif_index) { - /* looped MFC entry */ - zlog_warn("%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -4; - } + if (iif_index == oif_index) { + /* looped MFC entry */ + zlog_warn( + "%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -4; + } #endif - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr) { - if (s_route->iif == iif_index && - s_route->oif_ttls[oif_index]) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - /* Ok, from here on out we will be making changes to the s_route structure, but if - * for some reason we fail to commit these changes to the kernel, we want to be able - * restore the state of the list. So copy the node data and if need be, we can copy - * back if it fails. - */ - original_s_route = static_route_alloc(); - if (!original_s_route) { - return -5; - } - memcpy(original_s_route, s_route, sizeof(struct static_route)); - - /* Route exists and has the same input interface, but adding a new output interface */ - if (s_route->iif == iif_index) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - ++s_route->c_oil.oil_ref_count; - } else { - /* input interface changed */ - s_route->iif = iif_index; - s_route->c_oil.oil.mfcc_parent = iif_index; + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + if (s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr) { + if (s_route->iif == iif_index + && s_route->oif_ttls[oif_index]) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + return -3; + } + + /* Ok, from here on out we will be making changes to the + * s_route structure, but if + * for some reason we fail to commit these changes to + * the kernel, we want to be able + * restore the state of the list. So copy the node data + * and if need be, we can copy + * back if it fails. + */ + original_s_route = static_route_alloc(); + if (!original_s_route) { + return -5; + } + memcpy(original_s_route, s_route, + sizeof(struct static_route)); + + /* Route exists and has the same input interface, but + * adding a new output interface */ + if (s_route->iif == iif_index) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + ++s_route->c_oil.oil_ref_count; + } else { + /* input interface changed */ + s_route->iif = iif_index; + s_route->c_oil.oil.mfcc_parent = iif_index; #ifdef PIM_ENFORCE_LOOPFREE_MFC - /* check to make sure the new input was not an old output */ - if (s_route->oif_ttls[iif_index]) { - s_route->oif_ttls[iif_index] = 0; - s_route->c_oil.oif_creation[iif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[iif_index] = 0; - --s_route->c_oil.oil_ref_count; - } + /* check to make sure the new input was not an + * old output */ + if (s_route->oif_ttls[iif_index]) { + s_route->oif_ttls[iif_index] = 0; + s_route->c_oil.oif_creation[iif_index] = + 0; + s_route->c_oil.oil + .mfcc_ttls[iif_index] = 0; + --s_route->c_oil.oil_ref_count; + } #endif - /* now add the new output, if it is new */ - if (!s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - } - } - - break; - } - } - - /* If node is null then we reached the end of the list without finding a match */ - if (!node) { - s_route = static_route_new(iif_index, oif_index, group, source); - listnode_add(qpim_static_route_list, s_route); - } - - if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) - { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - /* Need to put s_route back to the way it was */ - if (original_s_route) { - memcpy(s_route, original_s_route, sizeof(struct static_route)); - } else { - /* we never stored off a copy, so it must have been a fresh new route */ - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - return -1; - } - - /* Make sure we free the memory for the route copy if used */ - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - return 0; + /* now add the new output, if it is new */ + if (!s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + s_route->c_oil.oil + .mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + } + } + + break; + } + } + + /* If node is null then we reached the end of the list without finding a + * match */ + if (!node) { + s_route = static_route_new(iif_index, oif_index, group, source); + listnode_add(qpim_static_route_list, s_route); + } + + if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + + /* Need to put s_route back to the way it was */ + if (original_s_route) { + memcpy(s_route, original_s_route, + sizeof(struct static_route)); + } else { + /* we never stored off a copy, so it must have been a + * fresh new route */ + listnode_delete(qpim_static_route_list, s_route); + pim_static_route_free(s_route); + } + + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + return -1; + } + + /* Make sure we free the memory for the route copy if used */ + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, oif_index, gifaddr_str, + sifaddr_str); + } + + return 0; } -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_del(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct listnode *nextnode = NULL; - struct static_route *s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : 0; - struct pim_interface *pim_oif = oif ? oif->info : 0; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } - - for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, s_route)) { - if (s_route->iif == iif_index && - s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr && - s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; - --s_route->c_oil.oil_ref_count; - - /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ - if (s_route->c_oil.oil_ref_count <= 0 ? - pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__) : pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - - return -1; - } - - s_route->c_oil.oif_creation[oif_index] = 0; - - if (s_route->c_oil.oil_ref_count <= 0) { - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - break; - } - } - - if (!node) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - return 0; + struct listnode *node = NULL; + struct listnode *nextnode = NULL; + struct static_route *s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : 0; + struct pim_interface *pim_oif = oif ? oif->info : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } + + for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, + s_route)) { + if (s_route->iif == iif_index + && s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr + && s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 0; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; + --s_route->c_oil.oil_ref_count; + + /* If there are no more outputs then delete the whole + * route, otherwise set the route with the new outputs + */ + if (s_route->c_oil.oil_ref_count <= 0 + ? pim_mroute_del(&s_route->c_oil, + __PRETTY_FUNCTION__) + : pim_mroute_add(&s_route->c_oil, + __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + + return -1; + } + + s_route->c_oil.oif_creation[oif_index] = 0; + + if (s_route->c_oil.oil_ref_count <= 0) { + listnode_delete(qpim_static_route_list, + s_route); + pim_static_route_free(s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, + oif_index, gifaddr_str, sifaddr_str); + } + + break; + } + } + + if (!node) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<ifaddr?>", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("<ifaddr?>", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + return -3; + } + + return 0; } -int -pim_static_write_mroute (struct vty *vty, struct interface *ifp) +int pim_static_write_mroute(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *node; - struct static_route *sroute; - int count = 0; - char sbuf[INET_ADDRSTRLEN]; - char gbuf[INET_ADDRSTRLEN]; - - if (!pim_ifp) - return 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute)) - { - pim_inet4_dump ("<ifaddr?>", sroute->group, gbuf, sizeof (gbuf)); - pim_inet4_dump ("<ifaddr?>", sroute->source, sbuf, sizeof (sbuf)); - if (sroute->iif == pim_ifp->mroute_vif_index) - { - int i; - for (i = 0; i < MAXVIFS; i++) - if (sroute->oif_ttls[i]) - { - struct interface *oifp = pim_if_find_by_vif_index (i); - if (sroute->source.s_addr == 0) - vty_out (vty, " ip mroute %s %s\n", oifp->name, gbuf); - else - vty_out (vty, " ip mroute %s %s %s\n", oifp->name, gbuf, - sbuf); - count ++; - } - } - } - - return count; + struct pim_interface *pim_ifp = ifp->info; + struct listnode *node; + struct static_route *sroute; + int count = 0; + char sbuf[INET_ADDRSTRLEN]; + char gbuf[INET_ADDRSTRLEN]; + + if (!pim_ifp) + return 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, sroute)) { + pim_inet4_dump("<ifaddr?>", sroute->group, gbuf, sizeof(gbuf)); + pim_inet4_dump("<ifaddr?>", sroute->source, sbuf, sizeof(sbuf)); + if (sroute->iif == pim_ifp->mroute_vif_index) { + int i; + for (i = 0; i < MAXVIFS; i++) + if (sroute->oif_ttls[i]) { + struct interface *oifp = + pim_if_find_by_vif_index(i); + if (sroute->source.s_addr == 0) + vty_out(vty, + " ip mroute %s %s\n", + oifp->name, gbuf); + else + vty_out(vty, + " ip mroute %s %s %s\n", + oifp->name, gbuf, sbuf); + count++; + } + } + } + + return count; } |