diff options
| -rw-r--r-- | bfdd/bfd.c | 160 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 4 | ||||
| -rw-r--r-- | doc/developer/tracing.rst | 25 | ||||
| -rw-r--r-- | lib/filter_cli.c | 24 | ||||
| -rw-r--r-- | nhrpd/nhrp_route.c | 26 | ||||
| -rw-r--r-- | nhrpd/nhrp_shortcut.c | 16 | ||||
| -rw-r--r-- | ospf6d/ospf6_abr.c | 51 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.c | 2 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 10 |
10 files changed, 168 insertions, 152 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index ca4bf94955..3e45bf0e04 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -1672,15 +1672,54 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2) static unsigned int bfd_key_hash_do(const void *p) { const struct bfd_session *bs = p; + struct bfd_key key = bs->key; - return jhash(&bs->key, sizeof(bs->key), 0); + /* + * Local address and interface name are optional and + * can be filled any time after session creation. + * Hash key should not depend on these fields. + */ + memset(&key.local, 0, sizeof(key.local)); + memset(key.ifname, 0, sizeof(key.ifname)); + + return jhash(&key, sizeof(key), 0); } static bool bfd_key_hash_cmp(const void *n1, const void *n2) { const struct bfd_session *bs1 = n1, *bs2 = n2; - return memcmp(&bs1->key, &bs2->key, sizeof(bs1->key)) == 0; + if (bs1->key.family != bs2->key.family) + return false; + if (bs1->key.mhop != bs2->key.mhop) + return false; + if (memcmp(&bs1->key.peer, &bs2->key.peer, sizeof(bs1->key.peer))) + return false; + if (memcmp(bs1->key.vrfname, bs2->key.vrfname, + sizeof(bs1->key.vrfname))) + return false; + + /* + * Local address is optional and can be empty. + * If both addresses are not empty and different, + * then the keys are different. + */ + if (memcmp(&bs1->key.local, &zero_addr, sizeof(bs1->key.local)) + && memcmp(&bs2->key.local, &zero_addr, sizeof(bs2->key.local)) + && memcmp(&bs1->key.local, &bs2->key.local, sizeof(bs1->key.local))) + return false; + + /* + * Interface name is optional and can be empty. + * If both names are not empty and different, + * then the keys are different. + */ + if (bs1->key.ifname[0] && bs2->key.ifname[0] + && memcmp(bs1->key.ifname, bs2->key.ifname, + sizeof(bs1->key.ifname))) + return false; + + return true; } @@ -1698,117 +1737,13 @@ struct bfd_session *bfd_id_lookup(uint32_t id) return hash_lookup(bfd_id_hash, &bs); } -struct bfd_key_walk_partial_lookup { - struct bfd_session *given; - struct bfd_session *result; -}; - -/* ignore some parameters */ -static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b, - void *data) -{ - struct bfd_key_walk_partial_lookup *ctx = - (struct bfd_key_walk_partial_lookup *)data; - struct bfd_session *given = ctx->given; - struct bfd_session *parsed = b->data; - - if (given->key.family != parsed->key.family) - return HASHWALK_CONTINUE; - if (given->key.mhop != parsed->key.mhop) - return HASHWALK_CONTINUE; - if (memcmp(&given->key.peer, &parsed->key.peer, - sizeof(struct in6_addr))) - return HASHWALK_CONTINUE; - if (memcmp(given->key.vrfname, parsed->key.vrfname, MAXNAMELEN)) - return HASHWALK_CONTINUE; - ctx->result = parsed; - /* ignore localaddr or interface */ - return HASHWALK_ABORT; -} - struct bfd_session *bfd_key_lookup(struct bfd_key key) { - struct bfd_session bs, *bsp; - struct bfd_key_walk_partial_lookup ctx; - char peer_buf[INET6_ADDRSTRLEN]; - - bs.key = key; - bsp = hash_lookup(bfd_key_hash, &bs); - if (bsp) - return bsp; - - inet_ntop(bs.key.family, &bs.key.peer, peer_buf, - sizeof(peer_buf)); - /* Handle cases where local-address is optional. */ - if (memcmp(&bs.key.local, &zero_addr, sizeof(bs.key.local))) { - memset(&bs.key.local, 0, sizeof(bs.key.local)); - bsp = hash_lookup(bfd_key_hash, &bs); - if (bsp) { - if (bglobal.debug_peer_event) { - char addr_buf[INET6_ADDRSTRLEN]; - inet_ntop(bs.key.family, &key.local, addr_buf, - sizeof(addr_buf)); - zlog_debug( - " peer %s found, but loc-addr %s ignored", - peer_buf, addr_buf); - } - return bsp; - } - } - - bs.key = key; - /* Handle cases where ifname is optional. */ - if (bs.key.ifname[0]) { - memset(bs.key.ifname, 0, sizeof(bs.key.ifname)); - bsp = hash_lookup(bfd_key_hash, &bs); - if (bsp) { - if (bglobal.debug_peer_event) - zlog_debug(" peer %s found, but ifp %s ignored", - peer_buf, key.ifname); - return bsp; - } - } + struct bfd_session bs; - /* Handle cases where local-address and ifname are optional. */ - if (bs.key.family == AF_INET) { - memset(&bs.key.local, 0, sizeof(bs.key.local)); - bsp = hash_lookup(bfd_key_hash, &bs); - if (bsp) { - if (bglobal.debug_peer_event) { - char addr_buf[INET6_ADDRSTRLEN]; - inet_ntop(bs.key.family, &bs.key.local, - addr_buf, sizeof(addr_buf)); - zlog_debug( - " peer %s found, but ifp %s and loc-addr %s ignored", - peer_buf, key.ifname, addr_buf); - } - return bsp; - } - } bs.key = key; - /* Handle case where a context more complex ctx is present. - * input has no iface nor local-address, but a context may - * exist. - * - * Only applies to IPv4, because IPv6 requires either - * local-address or interface. - */ - if (!bs.key.mhop && bs.key.family == AF_INET) { - ctx.result = NULL; - ctx.given = &bs; - hash_walk(bfd_key_hash, &bfd_key_lookup_ignore_partial_walker, - &ctx); - /* change key */ - if (ctx.result) { - bsp = ctx.result; - if (bglobal.debug_peer_event) - zlog_debug( - " peer %s found, but ifp and/or loc-addr params ignored", - peer_buf); - } - } - return bsp; + return hash_lookup(bfd_key_hash, &bs); } /* @@ -1832,16 +1767,11 @@ struct bfd_session *bfd_id_delete(uint32_t id) struct bfd_session *bfd_key_delete(struct bfd_key key) { - struct bfd_session bs, *bsp; + struct bfd_session bs; bs.key = key; - bsp = hash_lookup(bfd_key_hash, &bs); - if (bsp == NULL && key.ifname[0]) { - memset(bs.key.ifname, 0, sizeof(bs.key.ifname)); - bsp = hash_lookup(bfd_key_hash, &bs); - } - return hash_release(bfd_key_hash, bsp); + return hash_release(bfd_key_hash, &bs); } /* Iteration functions. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 19761d701a..f63a2b0247 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8272,7 +8272,7 @@ bgp_path_selection_reason2str(enum bgp_path_selection_reason reason) case bgp_path_selection_router_id: return "Router ID"; case bgp_path_selection_cluster_length: - return "Cluser length"; + return "Cluster length"; case bgp_path_selection_stale: return "Path Staleness"; case bgp_path_selection_local_configured: diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 8d06a4b374..f8ef5e2aa2 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5020,7 +5020,7 @@ ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd, DEFUN_YANG (no_neighbor_set_peer_group, no_neighbor_set_peer_group_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -5041,7 +5041,7 @@ DEFUN_YANG (no_neighbor_set_peer_group, } ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Member of the peer-group\n" "Peer-group name\n") diff --git a/doc/developer/tracing.rst b/doc/developer/tracing.rst index d54f6c7aaa..c194ae1270 100644 --- a/doc/developer/tracing.rst +++ b/doc/developer/tracing.rst @@ -308,6 +308,31 @@ Limitations Tracers do not like ``fork()`` or ``dlopen()``. LTTng has some workarounds for this involving interceptor libraries using ``LD_PRELOAD``. +If you're running FRR in a typical daemonizing way (``-d`` to the daemons) +you'll need to run the daemons like so: + +.. code-block:: shell + + LD_PRELOAD=liblttng-ust-fork.so <daemon> + + +If you're using systemd this you can accomplish this for all daemons by +modifying ``frr.service`` like so: + +.. code-block:: diff + + --- a/frr.service + +++ b/frr.service + @@ -7,6 +7,7 @@ Before=network.target + OnFailure=heartbeat-failed@%n.service + + [Service] + +Environment="LD_PRELOAD=liblttng-ust-fork.so" + Nice=-5 + Type=forking + NotifyAccess=all + + USDT tracepoints are relatively high overhead and probably shouldn't be used for "flight recorder" functionality, i.e. enabling and passively recording all events for monitoring purposes. It's generally okay to use LTTng like this, diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 54b6cda9a5..5d66a9fc73 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -259,7 +259,7 @@ DEFPY_YANG( /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ dnode = yang_dnode_get(running_config->dnode, xpath); @@ -268,7 +268,7 @@ DEFPY_YANG( mask_str ? mask_str : CISCO_HOST_WILDCARD_MASK, NULL, NULL); if (sseq == -1) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); @@ -436,7 +436,7 @@ DEFPY_YANG( /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ dnode = yang_dnode_get(running_config->dnode, xpath); @@ -469,7 +469,7 @@ DEFPY_YANG( "0.0.0.0", CISCO_ANY_WILDCARD_MASK); } if (sseq == -1) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); @@ -588,7 +588,7 @@ DEFPY_YANG( /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ dnode = yang_dnode_get(running_config->dnode, xpath); @@ -601,7 +601,7 @@ DEFPY_YANG( sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, exact); if (sseq == -1) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); @@ -786,7 +786,7 @@ DEFPY_YANG( /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ dnode = yang_dnode_get(running_config->dnode, xpath); @@ -799,7 +799,7 @@ DEFPY_YANG( sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, exact); if (sseq == -1) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); @@ -979,7 +979,7 @@ DEFPY_YANG( /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ dnode = yang_dnode_get(running_config->dnode, xpath); @@ -992,7 +992,7 @@ DEFPY_YANG( sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, false); if (sseq == -1) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); @@ -1277,7 +1277,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, /* Access-list must exist before entries. */ if (yang_dnode_exists(running_config->dnode, xpath) == false) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; /* Use access-list data structure to fetch sequence. */ assert(action != NULL); @@ -1290,7 +1290,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, pl = nb_running_get_entry(dnode, NULL, true); pentry = prefix_list_entry_lookup(pl, p, plt, -1, le, ge); if (pentry == NULL) - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq); diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index ce2b1fe2ff..334f468c18 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -98,6 +98,7 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, { struct zapi_route api; struct zapi_nexthop *api_nh; + union sockunion *nexthop_ref = (union sockunion *)nexthop; if (zclient->sock < 0) return; @@ -133,8 +134,14 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, switch (api.prefix.family) { case AF_INET: - if (nexthop) { - api_nh->gate.ipv4 = nexthop->sin.sin_addr; + if (api.prefix.prefixlen == IPV4_MAX_BITLEN && + nexthop_ref && + memcmp(&nexthop_ref->sin.sin_addr, &api.prefix.u.prefix4, + sizeof(struct in_addr)) == 0) { + nexthop_ref = NULL; + } + if (nexthop_ref) { + api_nh->gate.ipv4 = nexthop_ref->sin.sin_addr; api_nh->type = NEXTHOP_TYPE_IPV4; } if (ifp) { @@ -146,8 +153,14 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, } break; case AF_INET6: - if (nexthop) { - api_nh->gate.ipv6 = nexthop->sin6.sin6_addr; + if (api.prefix.prefixlen == IPV6_MAX_BITLEN && + nexthop_ref && + memcmp(&nexthop_ref->sin6.sin6_addr, &api.prefix.u.prefix6, + sizeof(struct in6_addr)) == 0) { + nexthop_ref = NULL; + } + if (nexthop_ref) { + api_nh->gate.ipv6 = nexthop_ref->sin6.sin6_addr; api_nh->type = NEXTHOP_TYPE_IPV6; } if (ifp) { @@ -170,8 +183,9 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, zlog_debug( "Zebra send: route %s %pFX nexthop %s metric %u count %d dev %s", add ? "add" : "del", &api.prefix, - nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, - buf, sizeof(buf)) + nexthop_ref ? inet_ntop(api.prefix.family, + &api_nh->gate, + buf, sizeof(buf)) : "<onlink>", api.metric, api.nexthop_num, ifp ? ifp->name : "none"); } diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 6ad0c9ea03..fbb883185a 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -51,18 +51,26 @@ static int nhrp_shortcut_do_expire(struct thread *t) static void nhrp_shortcut_cache_notify(struct notifier_block *n, unsigned long cmd) { + char buf2[PREFIX_STRLEN]; + struct nhrp_shortcut *s = container_of(n, struct nhrp_shortcut, cache_notifier); + struct nhrp_cache *c = s->cache; + if (c) + sockunion2str(&c->remote_addr, buf2, sizeof(buf2)); + else + snprintf(buf2, sizeof(buf2), "(unspec)"); switch (cmd) { case NOTIFY_CACHE_UP: if (!s->route_installed) { debugf(NHRP_DEBUG_ROUTE, - "Shortcut: route install %pFX nh (unspec) dev %s", - s->p, s->cache->ifp->name); + "Shortcut: route install %pFX nh %s dev %s", + s->p, buf2, c && c->ifp ? + c->ifp->name : "<unk>"); - nhrp_route_announce(1, s->type, s->p, s->cache->ifp, - &s->cache->remote_addr, 0); + nhrp_route_announce(1, s->type, s->p, c ? c->ifp : NULL, + c ? &c->remote_addr : NULL, 0); s->route_installed = 1; } break; diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 7bd51138b3..abcdb40547 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -757,6 +757,10 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old, struct ospf6_route_table *table) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix, + listcount(old->paths)); + if (listcount(old->paths) > 1) { struct listnode *anode, *anext, *nnode, *rnode, *rnext; struct ospf6_path *o_path; @@ -765,13 +769,15 @@ void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old, for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) { if (o_path->origin.adv_router != lsa->header->adv_router - && o_path->origin.id != lsa->header->id) + || o_path->origin.id != lsa->header->id) continue; for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) { for (ALL_LIST_ELEMENTS(old->nh_list, rnode, rnext, rnh)) { if (!ospf6_nexthop_is_same(rnh, nh)) continue; + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("deleted nexthop"); listnode_delete(old->nh_list, rnh); ospf6_nexthop_delete(rnh); } @@ -834,14 +840,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) bool old_entry_updated = false; struct ospf6_path *path, *o_path, *ecmp_path; struct listnode *anode; + bool add_route = false; memset(&prefix, 0, sizeof(prefix)); if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) { if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) { is_debug++; - zlog_debug("%s: Examin %s in area %s", __func__, - lsa->name, oa->name); + zlog_debug("%s: LSA %s age %d in area %s", __func__, + lsa->name, ospf6_lsa_age_current(lsa), + oa->name); } prefix_lsa = @@ -860,8 +868,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) { if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) { is_debug++; - zlog_debug("%s: Examin %s in area %s", __func__, - lsa->name, oa->name); + zlog_debug("%s: LSA %s age %d in area %s", __func__, + lsa->name, ospf6_lsa_age_current(lsa), + oa->name); } router_lsa = @@ -885,8 +894,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) /* Find existing route */ route = ospf6_route_lookup(&prefix, table); - if (route) + if (route) { ospf6_route_lock(route); + if (is_debug) + zlog_debug("%s: route %pFX, paths %d", __func__, + &prefix, listcount(route->paths)); + } while (route && ospf6_route_is_prefix(&prefix, route)) { if (route->path.area_id == oa->area_id && route->path.origin.type == lsa->header->type @@ -939,6 +952,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) return; } + /* (2) if the LSA is self-originated, ignore */ if (lsa->header->adv_router == oa->ospf6->router_id) { if (is_debug) @@ -1013,8 +1027,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) { if (is_debug) zlog_debug( - "%s: ABR router entry does not exist, ignore", - __func__); + "%s: ABR router entry %pFX does not exist, ignore", + __func__, &abr_prefix); if (old) { if (old->type == OSPF6_DEST_TYPE_ROUTER && oa->intra_brouter_calc) { @@ -1027,7 +1041,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) zlog_debug( "%s: remove old entry: %s %p ", __func__, buf, (void *)old); - ospf6_route_remove(old, table); + ospf6_abr_old_route_remove(lsa, old, table); } } return; @@ -1091,7 +1105,11 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) are identical. */ old = ospf6_route_lookup(&prefix, table); - + if (old) { + if (is_debug) + zlog_debug("%s: found old route %pFX, paths %d", + __func__, &prefix, listcount(old->paths)); + } for (old_route = old; old_route; old_route = old_route->next) { if (!ospf6_route_is_same(old_route, route) || (old_route->type != route->type) || @@ -1173,7 +1191,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) "%s: Update route: %s %p old cost %u new cost %u nh %u", __func__, buf, (void *)old_route, old_route->path.cost, route->path.cost, - listcount(route->nh_list)); + listcount(old_route->nh_list)); /* For Inter-Prefix route: Update RIB/FIB, * For Inter-Router trigger summary update @@ -1186,10 +1204,19 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) break; } + /* If the old entry is not updated and old entry not found or old entry + * does not match with the new entry then add the new route + */ if (old_entry_updated == false) { + if ((old == NULL) || (old->type != route->type) + || (old->path.type != route->path.type)) + add_route = true; + } + + if (add_route) { if (is_debug) { zlog_debug( - "%s: Install route: %s cost %u nh %u adv_router %pI4", + "%s: Install new route: %s cost %u nh %u adv_router %pI4", __func__, buf, route->path.cost, listcount(route->nh_list), &route->path.origin.adv_router); diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index b51aa17960..2abe64ac60 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1449,6 +1449,8 @@ static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route, g_route->path.origin.id = h_path->origin.id; g_route->path.origin.adv_router = h_path->origin.adv_router; + if (nroute) + ospf6_route_unlock(nroute); break; } } diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index ef39b6c2f6..343e406f28 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2987,6 +2987,16 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf) } } + if (ospf->vrf_id == VRF_DEFAULT && ospf->vrf_id != ifp->vrf_id) { + /* + * We may have a situation where l3mdev_accept == 1 + * let's just kindly drop the packet and move on. + * ospf really really really does not like when + * we receive the same packet multiple times. + */ + return OSPF_READ_CONTINUE; + } + /* Self-originated packet should be discarded silently. */ if (ospf_if_lookup_by_local_addr(ospf, NULL, iph->ip_src)) { if (IS_DEBUG_OSPF_PACKET(0, RECV)) { |
