summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_trace.h141
-rw-r--r--bgpd/bgp_zebra.c42
-rw-r--r--debian/frr-pythontools.install1
-rw-r--r--doc/developer/conf.py1
-rw-r--r--doc/developer/link-state.rst19
-rw-r--r--doc/developer/lists.rst24
-rw-r--r--doc/developer/locking.rst8
-rw-r--r--doc/developer/logging.rst6
-rw-r--r--doc/developer/memtypes.rst2
-rw-r--r--doc/developer/rcu.rst8
-rw-r--r--doc/developer/topotests.rst11
-rw-r--r--doc/user/ospf6d.rst17
-rw-r--r--lib/if.c276
-rw-r--r--lib/if.h13
-rw-r--r--lib/vrf.c22
-rw-r--r--lib/zclient.c6
-rw-r--r--ospf6d/ospf6_abr.c107
-rw-r--r--ospf6d/ospf6_area.c22
-rw-r--r--ospf6d/ospf6_area.h1
-rw-r--r--ospf6d/ospf6_flood.c16
-rw-r--r--ospf6d/ospf6_gr.c2
-rw-r--r--ospf6d/ospf6_interface.c6
-rw-r--r--ospf6d/ospf6_lsa.c6
-rw-r--r--ospf6d/ospf6_lsa.h5
-rw-r--r--ospf6d/ospf6_neighbor.c2
-rw-r--r--ospf6d/ospf6_nssa.c487
-rw-r--r--ospf6d/ospf6_nssa.h4
-rw-r--r--ospf6d/ospf6_route.c1
-rw-r--r--ospf6d/ospf6_route.h21
-rw-r--r--ospf6d/ospf6_top.c12
-rw-r--r--ospf6d/subdir.am1
-rw-r--r--ospfd/ospf_gr.c60
-rw-r--r--ospfd/ospf_interface.c4
-rw-r--r--ospfd/ospf_packet.c64
-rw-r--r--ospfd/ospf_vty.c4
-rw-r--r--pimd/pim_iface.c3
-rw-r--r--redhat/frr.spec.in3
-rw-r--r--tests/topotests/ospf6_topo2/r1/ospf6d.conf7
-rw-r--r--tests/topotests/ospf6_topo2/r2/ospf6d.conf11
-rw-r--r--tests/topotests/ospf6_topo2/r3/ospf6d.conf7
-rw-r--r--tests/topotests/ospf6_topo2/r4/ospf6d.conf7
-rw-r--r--tests/topotests/ospf6_topo2/test_ospf6_topo2.py100
-rwxr-xr-xtools/frr_babeltrace.py185
-rw-r--r--tools/subdir.am2
-rw-r--r--zebra/if_ioctl.c6
-rw-r--r--zebra/if_netlink.c12
-rw-r--r--zebra/interface.c16
-rw-r--r--zebra/kernel_socket.c6
-rw-r--r--zebra/zebra_vty.c7
49 files changed, 1031 insertions, 763 deletions
diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h
index 91a190722b..14149b5139 100644
--- a/bgpd/bgp_trace.h
+++ b/bgpd/bgp_trace.h
@@ -334,6 +334,147 @@ TRACEPOINT_EVENT(
)
)
TRACEPOINT_LOGLEVEL(frr_bgp, evpn_nh_rmac_zsend, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_es_add_zrecv,
+ TP_ARGS(esi_t *, esi, struct in_addr, vtep,
+ uint8_t, active, uint8_t, bypass, uint16_t, df_pref),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer(uint8_t, active, active)
+ ctf_integer(uint8_t, bypass, bypass)
+ ctf_integer(uint16_t, df_pref, df_pref)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_add_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_es_del_zrecv,
+ TP_ARGS(esi_t *, esi),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_del_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_es_evi_add_zrecv,
+ TP_ARGS(esi_t *, esi, vni_t, vni),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_add_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_mh_local_es_evi_del_zrecv,
+ TP_ARGS(esi_t *, esi, vni_t, vni),
+ TP_FIELDS(
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer(vni_t, vni, vni)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_del_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_vni_add_zrecv,
+ TP_ARGS(vni_t, vni, struct in_addr, vtep, vrf_id_t, vrf,
+ struct in_addr, mc_grp),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer_network_hex(unsigned int, mc_grp,
+ mc_grp.s_addr)
+ ctf_integer(int, vrf, vrf)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_add_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_vni_del_zrecv,
+ TP_ARGS(vni_t, vni),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_del_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_macip_add_zrecv,
+ TP_ARGS(vni_t, vni, struct ethaddr *, mac,
+ struct ipaddr *, ip, uint32_t, flags,
+ uint32_t, seqnum, esi_t *, esi),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ ctf_array(unsigned char, mac, mac,
+ sizeof(struct ethaddr))
+ ctf_array(unsigned char, ip, ip,
+ sizeof(struct ipaddr))
+ ctf_integer(uint32_t, flags, flags)
+ ctf_integer(uint32_t, seq, seqnum)
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_add_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_macip_del_zrecv,
+ TP_ARGS(vni_t, vni, struct ethaddr *, mac, struct ipaddr *, ip,
+ int, state),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ ctf_array(unsigned char, mac, mac,
+ sizeof(struct ethaddr))
+ ctf_array(unsigned char, ip, ip,
+ sizeof(struct ipaddr))
+ ctf_integer(int, state, state)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_del_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_l3vni_add_zrecv,
+ TP_ARGS(vni_t, vni, vrf_id_t, vrf,
+ struct ethaddr *, svi_rmac,
+ struct ethaddr *, vrr_rmac, int, filter,
+ struct in_addr, vtep, int, svi_ifindex,
+ bool, anycast_mac),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer(int, vrf, vrf)
+ ctf_array(unsigned char, svi_rmac, svi_rmac,
+ sizeof(struct ethaddr))
+ ctf_array(unsigned char, vrr_rmac, vrr_rmac,
+ sizeof(struct ethaddr))
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer(int, filter, filter)
+ ctf_integer(int, svi_ifindex, svi_ifindex)
+ ctf_string(anycast_mac, anycast_mac ? "y" : "n")
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_add_zrecv, TRACE_INFO)
+
+TRACEPOINT_EVENT(
+ frr_bgp,
+ evpn_local_l3vni_del_zrecv,
+ TP_ARGS(vni_t, vni, vrf_id_t, vrf),
+ TP_FIELDS(
+ ctf_integer(vni_t, vni, vni)
+ ctf_integer(int, vrf, vrf)
+ )
+)
+TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_del_zrecv, TRACE_INFO)
/* clang-format on */
#include <lttng/tracepoint-event.h>
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 0249d53f02..6161f56fe6 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -64,6 +64,7 @@
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_mh.h"
#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_trace.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
@@ -2773,6 +2774,9 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS)
esi_to_str(&esi, buf, sizeof(buf)), &originator_ip,
active, df_pref, bypass ? "bypass" : "");
+ frrtrace(5, frr_bgp, evpn_mh_local_es_add_zrecv, &esi, originator_ip,
+ active, bypass, df_pref);
+
bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref,
!!bypass);
@@ -2798,6 +2802,8 @@ static int bgp_zebra_process_local_es_del(ZAPI_CALLBACK_ARGS)
zlog_debug("Rx del ESI %s",
esi_to_str(&esi, buf, sizeof(buf)));
+ frrtrace(1, frr_bgp, evpn_mh_local_es_del_zrecv, &esi);
+
bgp_evpn_local_es_del(bgp, &esi);
return 0;
@@ -2824,10 +2830,15 @@ static int bgp_zebra_process_local_es_evi(ZAPI_CALLBACK_ARGS)
ZEBRA_VNI_ADD ? "add" : "del",
esi_to_str(&esi, buf, sizeof(buf)), vni);
- if (cmd == ZEBRA_LOCAL_ES_EVI_ADD)
+ if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) {
+ frrtrace(2, frr_bgp, evpn_mh_local_es_evi_add_zrecv, &esi, vni);
+
bgp_evpn_local_es_evi_add(bgp, &esi, vni);
- else
+ } else {
+ frrtrace(2, frr_bgp, evpn_mh_local_es_evi_del_zrecv, &esi, vni);
+
bgp_evpn_local_es_evi_del(bgp, &esi, vni);
+ }
return 0;
}
@@ -2862,6 +2873,10 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
filter ? "prefix-routes-only" : "none",
svi_ifindex);
+ frrtrace(8, frr_bgp, evpn_local_l3vni_add_zrecv, l3vni, vrf_id,
+ &svi_rmac, &vrr_rmac, filter, originator_ip,
+ svi_ifindex, is_anycast_mac);
+
bgp_evpn_local_l3vni_add(l3vni, vrf_id, &svi_rmac, &vrr_rmac,
originator_ip, filter, svi_ifindex,
is_anycast_mac);
@@ -2870,6 +2885,8 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
zlog_debug("Rx L3-VNI DEL VRF %s VNI %u",
vrf_id_to_name(vrf_id), l3vni);
+ frrtrace(2, frr_bgp, evpn_local_l3vni_del_zrecv, l3vni, vrf_id);
+
bgp_evpn_local_l3vni_del(l3vni, vrf_id);
}
@@ -2906,13 +2923,19 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS)
vrf_id_to_name(vrf_id), vni,
vrf_id_to_name(tenant_vrf_id), svi_ifindex);
- if (cmd == ZEBRA_VNI_ADD)
+ if (cmd == ZEBRA_VNI_ADD) {
+ frrtrace(4, frr_bgp, evpn_local_vni_add_zrecv, vni, vtep_ip,
+ tenant_vrf_id, mcast_grp);
+
return bgp_evpn_local_vni_add(
bgp, vni,
vtep_ip.s_addr != INADDR_ANY ? vtep_ip : bgp->router_id,
tenant_vrf_id, mcast_grp, svi_ifindex);
- else
+ } else {
+ frrtrace(1, frr_bgp, evpn_local_vni_del_zrecv, vni);
+
return bgp_evpn_local_vni_del(bgp, vni);
+ }
}
static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
@@ -2968,11 +2991,18 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
&mac, &ip, vni, seqnum, state,
esi_to_str(&esi, buf2, sizeof(buf2)));
- if (cmd == ZEBRA_MACIP_ADD)
+ if (cmd == ZEBRA_MACIP_ADD) {
+ frrtrace(6, frr_bgp, evpn_local_macip_add_zrecv, vni, &mac, &ip,
+ flags, seqnum, &esi);
+
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip,
flags, seqnum, &esi);
- else
+ } else {
+ frrtrace(4, frr_bgp, evpn_local_macip_del_zrecv, vni, &mac, &ip,
+ state);
+
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state);
+ }
}
static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
diff --git a/debian/frr-pythontools.install b/debian/frr-pythontools.install
index 5f7eaebed5..820895ce68 100644
--- a/debian/frr-pythontools.install
+++ b/debian/frr-pythontools.install
@@ -1,2 +1,3 @@
usr/lib/frr/frr-reload.py
usr/lib/frr/generate_support_bundle.py
+usr/lib/frr/frr_babeltrace.py
diff --git a/doc/developer/conf.py b/doc/developer/conf.py
index 8f282c0790..61df6e0e60 100644
--- a/doc/developer/conf.py
+++ b/doc/developer/conf.py
@@ -138,6 +138,7 @@ exclude_patterns = [
"_build",
"building-libyang.rst",
"topotests-snippets.rst",
+ "topotests-markers.rst",
"include-compile.rst",
]
diff --git a/doc/developer/link-state.rst b/doc/developer/link-state.rst
index 1cbaf27ffe..2072595e36 100644
--- a/doc/developer/link-state.rst
+++ b/doc/developer/link-state.rst
@@ -53,15 +53,15 @@ Data structures
3 types of Link State structure have been defined:
-.. c:type:: struct ls_node
+.. c:struct:: ls_node
that groups all information related to a node
-.. c:type:: struct ls_attributes
+.. c:struct:: ls_attributes
that groups all information related to a link
-.. c:type:: struct ls_prefix
+.. c:struct:: ls_prefix
that groups all information related to a prefix
@@ -73,7 +73,7 @@ identifier which advertises the Link State and a bit mask as flags to
indicates which parameters are valid i.e. for which the value is valid and
corresponds to a Link State information conveyed by the routing protocol.
-.. c:type:: struct ls_node_id
+.. c:struct:: ls_node_id
defines the Node identifier as router ID IPv4 address plus the area ID for
OSPF or the ISO System ID plus the IS-IS level for IS-IS.
@@ -159,10 +159,11 @@ A unique Key is used to identify both Vertices and Edges within the Graph.
4 data structures have been defined to implement the Graph model:
-.. c:type:: struct ls_vertex
-.. c:type:: struct ls_edge
-.. c:type:: struct ls_prefix
-.. c:type:: struct ls_ted
+.. c:struct:: ls_vertex
+.. c:struct:: ls_edge
+.. c:struct:: ls_ted
+
+ - :c:struct:`ls_prefix`
TED stores Vertex, Edge and Subnet elements with a RB Tree structure.
The Vertex key corresponds to the Router ID for OSPF and ISO System ID for
@@ -412,7 +413,7 @@ Data Structures
The Link State Message is defined to convey Link State parameters from
the routing protocol (OSPF or IS-IS) to other daemons e.g. BGP.
-.. c:type:: struct ls_message
+.. c:struct:: ls_message
The structure is composed of:
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index 553bd1f596..718e404764 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -182,7 +182,7 @@ Common iteration macros
The following iteration macros work across all data structures:
-.. c:function:: frr_each(Z, &head, item)
+.. c:macro:: frr_each(Z, head, item)
Equivalent to:
@@ -193,7 +193,7 @@ The following iteration macros work across all data structures:
Note that this will fail if the list is modified while being iterated
over.
-.. c:function:: frr_each_safe(Z, &head, item)
+.. c:macro:: frr_each_safe(Z, head, item)
Same as the previous, but the next element is pre-loaded into a "hidden"
variable (named ``Z_safe``.) Equivalent to:
@@ -212,7 +212,7 @@ The following iteration macros work across all data structures:
tables is resized while iterating. This will cause items to be
skipped or iterated over twice.
-.. c:function:: frr_each_from(Z, &head, item, from)
+.. c:macro:: frr_each_from(Z, head, item, from)
Iterates over the list, starting at item ``from``. This variant is "safe"
as in the previous macro. Equivalent to:
@@ -297,7 +297,7 @@ The following documentation assumes that a list has been defined using
affected by the "modification while iterating" problem. To remove
all items from a hash table, use the loop demonstrated above.
-.. c:function:: const itemtype *Z_next(const struct Z_head *, const itemtype *prev)
+.. c:function:: const itemtype *Z_const_next(const struct Z_head *, const itemtype *prev)
.. c:function:: itemtype *Z_next(struct Z_head *, itemtype *prev)
Return the item that follows after ``prev``, or ``NULL`` if ``prev`` is
@@ -346,7 +346,7 @@ are several functions exposed to insert data:
``item`` must not be ``NULL`` for any of the following functions.
-.. c:function:: DECLARE_XXX(Z, type, field)
+.. c:macro:: DECLARE_XXX(Z, type, field)
:param listtype XXX: ``LIST``, ``DLIST`` or ``ATOMLIST`` to select a data
structure implementation.
@@ -403,7 +403,7 @@ Sorted data structures do not need to have an insertion position specified,
therefore the insertion calls are different from unsorted lists. Also,
sorted lists can be searched for a value.
-.. c:function:: DECLARE_XXX_UNIQ(Z, type, field, compare_func)
+.. c:macro:: DECLARE_XXX_UNIQ(Z, type, field, compare_func)
:param listtype XXX: One of the following:
``SORTLIST`` (single-linked sorted list), ``SKIPLIST`` (skiplist),
@@ -423,7 +423,7 @@ sorted lists can be searched for a value.
``int function(const itemtype *, const itemtype*)``. This function
may be static if the list is only used in one file.
-.. c:function:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func)
+.. c:macro:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func)
Same as above, but allow adding multiple items to the list that compare
as equal in ``compare_func``. Ordering between these items is undefined
@@ -439,7 +439,7 @@ sorted lists can be searched for a value.
For ``_NONUNIQ`` lists, this function always returns NULL since ``item``
can always be successfully added to the list.
-.. c:function:: const itemtype *Z_find(const struct Z_head *, const itemtype *ref)
+.. c:function:: const itemtype *Z_const_find(const struct Z_head *, const itemtype *ref)
.. c:function:: itemtype *Z_find(struct Z_head *, const itemtype *ref)
Search the list for an item that compares equal to ``ref``. If no equal
@@ -461,13 +461,13 @@ sorted lists can be searched for a value.
containing non-unique items, more than one item may compare as equal to
the item that is searched for.
-.. c:function:: const itemtype *Z_find_gteq(const struct Z_head *, const itemtype *ref)
+.. c:function:: const itemtype *Z_const_find_gteq(const struct Z_head *, const itemtype *ref)
.. c:function:: itemtype *Z_find_gteq(struct Z_head *, const itemtype *ref)
Search the list for an item that compares greater or equal to
``ref``. See :c:func:`Z_find()` above.
-.. c:function:: const itemtype *Z_find_lt(const struct Z_head *, const itemtype *ref)
+.. c:function:: const itemtype *Z_const_find_lt(const struct Z_head *, const itemtype *ref)
.. c:function:: itemtype *Z_find_lt(struct Z_head *, const itemtype *ref)
Search the list for an item that compares less than
@@ -477,9 +477,9 @@ sorted lists can be searched for a value.
API for hash tables
-------------------
-.. c:function:: DECLARE_XXX(Z, type, field, compare_func, hash_func)
+.. c:macro:: DECLARE_HASH(Z, type, field, compare_func, hash_func)
- :param listtype XXX: Only ``HASH`` is currently available.
+ :param listtype HASH: Only ``HASH`` is currently available.
:param token Z: Gives the name prefix that is used for the functions
created for this instantiation. ``DECLARE_XXX(foo, ...)``
gives ``struct foo_item``, ``foo_add()``, ``foo_count()``, etc. Note
diff --git a/doc/developer/locking.rst b/doc/developer/locking.rst
index d698789f9f..c8366480d2 100644
--- a/doc/developer/locking.rst
+++ b/doc/developer/locking.rst
@@ -7,7 +7,9 @@ FRR ships two small wrappers around ``pthread_mutex_lock()`` /
``pthread_mutex_unlock``. Use ``#include "frr_pthread.h"`` to get these
macros.
-.. c:function:: frr_with_mutex(pthread_mutex_t *mutex)
+.. c:macro:: frr_with_mutex(mutex)
+
+ (With ``pthread_mutex_t *mutex``.)
Begin a C statement block that is executed with the mutex locked. Any
exit from the block (``break``, ``return``, ``goto``, end of block) will
@@ -43,7 +45,9 @@ macros.
statement works correctly, FRR coding style requires that this macro always
be used with a ``{ ... }`` block.
-.. c:function:: frr_mutex_lock_autounlock(pthread_mutex_t *mutex)
+.. c:macro:: frr_mutex_lock_autounlock(mutex)
+
+ (With ``pthread_mutex_t *mutex``.)
Lock mutex and unlock at the end of the current C statement block::
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
index 681fc1173c..eaf8625efa 100644
--- a/doc/developer/logging.rst
+++ b/doc/developer/logging.rst
@@ -489,7 +489,7 @@ calls to :c:func:`zlog_tls_buffer_flush()` in appropriate places:
buffer. This function is safe to call regardless of the per-thread log
buffer being set up / in use or not.
-When working with threads that do not use the :c:type:`struct thread_master`
+When working with threads that do not use the :c:struct:`thread_master`
event loop, per-thread buffers can be managed with:
.. c:function:: void zlog_tls_buffer_init(void)
@@ -531,7 +531,7 @@ that they use.
Basic internals
^^^^^^^^^^^^^^^
-.. c:type:: struct zlog_target
+.. c:struct:: zlog_target
This struct needs to be filled in by any log target and then passed to
:c:func:`zlog_target_replace()`. After it has been registered,
@@ -570,7 +570,7 @@ Basic internals
Allocates a logging target struct. Note that the ``oldzt`` argument may be
``NULL`` to allocate a "from scratch". If ``oldzt`` is not ``NULL``, the
- generic bits in :c:type:`struct zlog_target` are copied. **Target specific
+ generic bits in :c:struct:`zlog_target` are copied. **Target specific
bits are not copied.**
.. c:function:: struct zlog_target *zlog_target_replace(struct zlog_target *oldzt, struct zlog_target *newzt)
diff --git a/doc/developer/memtypes.rst b/doc/developer/memtypes.rst
index 08dad7fb68..2e181c4f2b 100644
--- a/doc/developer/memtypes.rst
+++ b/doc/developer/memtypes.rst
@@ -42,7 +42,7 @@ Example:
Definition
----------
-.. c:type:: struct memtype
+.. c:struct:: memtype
This is the (internal) type used for MTYPE definitions. The macros below
should be used to create these, but in some cases it is useful to pass a
diff --git a/doc/developer/rcu.rst b/doc/developer/rcu.rst
index c2ddf93f53..c8248194b7 100644
--- a/doc/developer/rcu.rst
+++ b/doc/developer/rcu.rst
@@ -133,9 +133,9 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks.
become invalid, as another thread may have called :c:func:`rcu_free` on
them.
-.. c:type:: struct rcu_head
-.. c:type:: struct rcu_head_close
-.. c:type:: struct rcu_action
+.. c:struct:: rcu_head
+.. c:struct:: rcu_head_close
+.. c:struct:: rcu_action
The ``rcu_head`` structures are small (16-byte) bits that contain the
queueing machinery for the RCU sweeper/cleanup mechanisms.
@@ -209,7 +209,7 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks.
Internals
^^^^^^^^^
-.. c:type:: struct rcu_thread
+.. c:struct:: rcu_thread
Per-thread state maintained by the RCU code, set up by the following
functions. A pointer to a thread's own ``rcu_thread`` is saved in
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
index b4f6ec521c..d8b3650944 100644
--- a/doc/developer/topotests.rst
+++ b/doc/developer/topotests.rst
@@ -137,14 +137,14 @@ Topotests must be run as root. Normally this will be accomplished through the
use of the ``sudo`` command. In order for topotests to be able to open new
windows (either XTerm or byobu/screen/tmux windows) certain environment
variables must be passed through the sudo command. One way to do this is to
-specify the :option:`-E` flag to ``sudo``. This will carry over most if not all
+specify the ``-E`` flag to ``sudo``. This will carry over most if not all
your environment variables include ``PATH``. For example:
.. code:: shell
sudo -E python3 -m pytest -s -v
-If you do not wish to use :option:`-E` (e.g., to avoid ``sudo`` inheriting
+If you do not wish to use ``-E`` (e.g., to avoid ``sudo`` inheriting
``PATH``) you can modify your `/etc/sudoers` config file to specifically pass
the environment variables required by topotests. Add the following commands to
your ``/etc/sudoers`` config file.
@@ -197,7 +197,7 @@ the run.
Here we see that 4 tests have failed. We an dig deeper by displaying the
captured logs and errors. First let's redisplay the results enumerated by adding
-the :option:`-E` flag
+the ``-E`` flag
.. code:: shell
@@ -385,7 +385,7 @@ to launch the given programs.
NOTE: you must run the topotest (pytest) such that your DISPLAY, STY or TMUX
environment variables are carried over. You can do this by passing the
-:option:`-E` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to
+``-E`` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to
automatically pass that environment variable through to the ``sudo``
environment.
@@ -903,6 +903,7 @@ Interface), from here you can call your router ``vtysh`` or even bash.
Here's the help text:
.. code:: shell
+
unet> help
Commands:
@@ -912,8 +913,6 @@ Here's the help text:
vtysh [hosts] :: open vtysh terminals for hosts
[hosts] <vtysh-command> :: execute vtysh-command on hosts
-.. code:: shell
-
Here are some commands example:
.. code:: shell
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 0b718fcdf2..624510323c 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -181,7 +181,7 @@ OSPF6 area
The `not-advertise` option, when present, prevents the summary route from
being advertised, effectively filtering the summarized routes.
-.. clicmd:: area A.B.C.D nssa [no-summary]
+.. clicmd:: area A.B.C.D nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]]
.. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]]
@@ -209,6 +209,21 @@ OSPF6 area
existence of a default route in the RIB that wasn't learned via the OSPF
protocol.
+.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
+
+.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
+
+ Summarize a group of external subnets into a single Type-7 LSA, which is
+ then translated to a Type-5 LSA and avertised to the backbone.
+ This command can only be used at the area boundary (NSSA ABR router).
+
+ By default, the metric of the summary route is calculated as the highest
+ metric among the summarized routes. The `cost` option, however, can be used
+ to set an explicit metric.
+
+ The `not-advertise` option, when present, prevents the summary route from
+ being advertised, effectively filtering the summarized routes.
+
.. clicmd:: area A.B.C.D export-list NAME
.. clicmd:: area (0-4294967295) export-list NAME
diff --git a/lib/if.c b/lib/if.c
index 4d7862022c..cb6270f5ec 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected");
DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label");
DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters");
+static void if_set_name(struct interface *ifp, const char *name);
static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
vrf_id_t vrf_id);
static int if_cmp_func(const struct interface *, const struct interface *);
@@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg)
}
/* Create new interface structure. */
-static struct interface *if_new(vrf_id_t vrf_id)
+static struct interface *if_new(struct vrf *vrf)
{
struct interface *ifp;
+ assert(vrf);
+
ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
ifp->ifindex = IFINDEX_INTERNAL;
ifp->name[0] = '\0';
- ifp->vrf_id = vrf_id;
+ ifp->vrf = vrf;
+ ifp->vrf_id = vrf->vrf_id;
ifp->connected = list_new();
ifp->connected->del = ifp_connected_free;
@@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp)
(*ifp_master.down_hook)(ifp);
}
-struct interface *if_create_name(const char *name, vrf_id_t vrf_id)
+static struct interface *if_create_name(const char *name, struct vrf *vrf)
{
struct interface *ifp;
- ifp = if_new(vrf_id);
+ ifp = if_new(vrf);
if_set_name(ifp, name);
@@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id)
return ifp;
}
-struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
-{
- struct interface *ifp;
-
- ifp = if_new(vrf_id);
-
- if_set_index(ifp, ifindex);
-
- hook_call(if_add, ifp);
- return ifp;
-}
-
/* Create new interface structure. */
void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
{
struct vrf *old_vrf, *vrf;
/* remove interface from old master vrf list */
- old_vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (old_vrf) {
- if (ifp->name[0] != '\0')
- IFNAME_RB_REMOVE(old_vrf, ifp);
+ old_vrf = ifp->vrf;
- if (ifp->ifindex != IFINDEX_INTERNAL)
- IFINDEX_RB_REMOVE(old_vrf, ifp);
- }
+ if (ifp->name[0] != '\0')
+ IFNAME_RB_REMOVE(old_vrf, ifp);
+
+ if (ifp->ifindex != IFINDEX_INTERNAL)
+ IFINDEX_RB_REMOVE(old_vrf, ifp);
ifp->vrf_id = vrf_id;
vrf = vrf_get(ifp->vrf_id, NULL);
+ ifp->vrf = vrf;
if (ifp->name[0] != '\0')
IFNAME_RB_INSERT(vrf, ifp);
@@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
* the interface and readding it in the new VRF, which would have
* several implications.
*/
- if (yang_module_find("frr-interface")) {
+ if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) {
struct lyd_node *if_dnode;
char oldpath[XPATH_MAXLEN];
char newpath[XPATH_MAXLEN];
@@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp)
void if_delete(struct interface **ifp)
{
struct interface *ptr = *ifp;
- struct vrf *vrf;
-
- vrf = vrf_lookup_by_id(ptr->vrf_id);
- assert(vrf);
+ struct vrf *vrf = ptr->vrf;
IFNAME_RB_REMOVE(vrf, ptr);
if (ptr->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(vrf, ptr);
+ if (!vrf_is_enabled(vrf))
+ vrf_delete(vrf);
+
if_delete_retain(ptr);
list_delete(&ptr->connected);
@@ -439,8 +431,8 @@ struct interface *if_lookup_by_name_all_vrf(const char *name)
if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
return NULL;
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- ifp = if_lookup_by_name(name, vrf->vrf_id);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ ifp = if_lookup_by_name_vrf(name, vrf);
if (ifp)
return ifp;
}
@@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz,
/* Get interface by name if given name interface doesn't exist create
one. */
-struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id)
+struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
+ const char *vrf_name)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
+ struct vrf *vrf;
switch (vrf_get_backend()) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
- ifp = if_lookup_by_name(name, vrf_id);
- if (ifp)
- return ifp;
- return if_create_name(name, vrf_id);
- case VRF_BACKEND_VRF_LITE:
- ifp = if_lookup_by_name_all_vrf(name);
+ vrf = vrf_get(vrf_id, vrf_name);
+ assert(vrf);
+
+ ifp = if_lookup_by_name_vrf(name, vrf);
if (ifp) {
- if (ifp->vrf_id == vrf_id)
- return ifp;
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if_update_to_new_vrf(ifp, vrf_id);
+ if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if_update_to_new_vrf(ifp, vrf_id);
+
return ifp;
}
- return if_create_name(name, vrf_id);
- }
-
- return NULL;
-}
-struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
-{
- struct interface *ifp;
-
- switch (vrf_get_backend()) {
- case VRF_BACKEND_UNKNOWN:
- case VRF_BACKEND_NETNS:
- ifp = if_lookup_by_ifindex(ifindex, vrf_id);
- if (ifp)
- return ifp;
- return if_create_ifindex(ifindex, vrf_id);
+ break;
case VRF_BACKEND_VRF_LITE:
- ifp = if_lookup_by_index_all_vrf(ifindex);
+ ifp = if_lookup_by_name_all_vrf(name);
if (ifp) {
- if (ifp->vrf_id == vrf_id)
- return ifp;
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if_update_to_new_vrf(ifp, vrf_id);
+ if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if_update_to_new_vrf(ifp, vrf_id);
+
return ifp;
}
- return if_create_ifindex(ifindex, vrf_id);
+
+ vrf = vrf_get(vrf_id, vrf_name);
+ assert(vrf);
+
+ break;
+ default:
+ return NULL;
}
- return NULL;
+ return if_create_name(name, vrf);
}
int if_set_index(struct interface *ifp, ifindex_t ifindex)
{
- struct vrf *vrf;
-
if (ifp->ifindex == ifindex)
return 0;
- vrf = vrf_get(ifp->vrf_id, NULL);
- assert(vrf);
-
/*
* If there is already an interface with this ifindex, we will collide
* on insertion, so don't even try.
@@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
return -1;
if (ifp->ifindex != IFINDEX_INTERNAL)
- IFINDEX_RB_REMOVE(vrf, ifp);
+ IFINDEX_RB_REMOVE(ifp->vrf, ifp);
ifp->ifindex = ifindex;
@@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
* already an interface with the desired ifindex at the top of
* the function. Nevertheless.
*/
- if (IFINDEX_RB_INSERT(vrf, ifp))
+ if (IFINDEX_RB_INSERT(ifp->vrf, ifp))
return -1;
}
return 0;
}
-void if_set_name(struct interface *ifp, const char *name)
+static void if_set_name(struct interface *ifp, const char *name)
{
- struct vrf *vrf;
-
- vrf = vrf_get(ifp->vrf_id, NULL);
- assert(vrf);
-
if (if_cmp_name_func(ifp->name, name) == 0)
return;
if (ifp->name[0] != '\0')
- IFNAME_RB_REMOVE(vrf, ifp);
+ IFNAME_RB_REMOVE(ifp->vrf, ifp);
strlcpy(ifp->name, name, sizeof(ifp->name));
if (ifp->name[0] != '\0')
- IFNAME_RB_INSERT(vrf, ifp);
+ IFNAME_RB_INSERT(ifp->vrf, ifp);
}
/* Does interface up ? */
@@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp)
struct listnode *node;
struct connected *c __attribute__((unused));
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) {
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+ for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
zlog_info(
"Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
- ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
+ ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex,
ifp->metric, ifp->mtu, ifp->mtu6,
if_flag_dump(ifp->flags));
- }
}
/* Interface printing for all interface. */
@@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str)
{
struct prefix *p;
struct interface *ifp;
- struct vrf *vrf;
char logbuf[BUFSIZ];
char buf[BUFSIZ];
ifp = connected->ifp;
p = connected->address;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
- str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id,
+ str, ifp->name, ifp->vrf->name, ifp->vrf_id,
prefix_family_str(p), p);
p = connected->destination;
@@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp)
void if_terminate(struct vrf *vrf)
{
struct interface *ifp;
- bool delete;
-
- /*
- * If the default VRF is being terminated or has
- * already been terminated it means that
- * the program is shutting down and we need to
- * delete all the interfaces. Otherwise, we only
- * need to move VRF's interfaces to the default VRF.
- */
- delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT
- || !vrf_lookup_by_id(VRF_DEFAULT);
while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name);
- if (delete) {
- if (ifp->node) {
- ifp->node->info = NULL;
- route_unlock_node(ifp->node);
- }
- if_delete(&ifp);
- } else {
- if_update_to_new_vrf(ifp, VRF_DEFAULT);
+ if (ifp->node) {
+ ifp->node->info = NULL;
+ route_unlock_node(ifp->node);
}
+ if_delete(&ifp);
}
}
@@ -1186,6 +1139,25 @@ void if_link_params_free(struct interface *ifp)
/* ----------- CLI commands ----------- */
+/* Guess the VRF of an interface. */
+static int vrfname_by_ifname(const char *ifname, const char **vrfname)
+{
+ struct vrf *vrf;
+ struct interface *ifp;
+ int count = 0;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ if (strmatch(ifp->name, ifname)) {
+ *vrfname = vrf->name;
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
/*
* XPath: /frr-interface:lib/interface
*/
@@ -1197,12 +1169,9 @@ DEFPY_YANG_NOSH (interface,
VRF_CMD_HELP_STR)
{
char xpath_list[XPATH_MAXLEN];
- vrf_id_t vrf_id;
struct interface *ifp;
- int ret;
-
- if (!vrf_name)
- vrf_name = VRF_DEFAULT_NAME;
+ struct vrf *vrf;
+ int ret, count;
/*
* This command requires special handling to maintain backward
@@ -1211,30 +1180,30 @@ DEFPY_YANG_NOSH (interface,
* interface is found, then a new one should be created on the default
* VRF.
*/
- VRF_GET_ID(vrf_id, vrf_name, false);
- ifp = if_lookup_by_name_all_vrf(ifname);
- if (ifp && ifp->vrf_id != vrf_id) {
- struct vrf *vrf;
-
+ if (vrf_is_backend_netns()) {
/*
- * Special case 1: a VRF name was specified, but the found
- * interface is associated to different VRF. Reject the command.
+ * For backward compatibility, if the VRF name is not specified
+ * and there is exactly one interface with this name in the
+ * system, use its VRF. Otherwise fallback to the default VRF.
*/
- if (vrf_id != VRF_DEFAULT) {
- vty_out(vty, "%% interface %s not in %s vrf\n", ifname,
- vrf_name);
- return CMD_WARNING_CONFIG_FAILED;
+ if (!vrf_name) {
+ count = vrfname_by_ifname(ifname, &vrf_name);
+ if (count != 1)
+ vrf_name = VRF_DEFAULT_NAME;
}
-
+ } else {
/*
- * Special case 2: a VRF name was *not* specified, and the found
- * interface is associated to a VRF other than the default one.
- * Update vrf_id and vrf_name to account for that.
+ * If the interface already exists, use its VRF regardless of
+ * what user specified. We can't have same interface name in
+ * different VRFs with VRF-lite backend.
*/
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- assert(vrf);
- vrf_id = ifp->vrf_id;
- vrf_name = vrf->name;
+ ifp = if_lookup_by_name_all_vrf(ifname);
+ if (ifp) {
+ vrf_name = ifp->vrf->name;
+ } else {
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
+ }
}
snprintf(xpath_list, sizeof(xpath_list),
@@ -1252,7 +1221,15 @@ DEFPY_YANG_NOSH (interface,
* all interface-level commands are converted to the new
* northbound model.
*/
- ifp = if_lookup_by_name(ifname, vrf_id);
+ if (vrf_is_backend_netns()) {
+ vrf = vrf_lookup_by_name(vrf_name);
+ if (vrf)
+ ifp = if_lookup_by_name_vrf(ifname, vrf);
+ else
+ ifp = NULL;
+ } else {
+ ifp = if_lookup_by_name_all_vrf(ifname);
+ }
if (ifp)
VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp);
}
@@ -1397,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args)
{
const char *ifname;
const char *vrfname;
- struct vrf *vrf;
struct interface *ifp;
ifname = yang_dnode_get_string(args->dnode, "./name");
@@ -1405,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args)
switch (args->event) {
case NB_EV_VALIDATE:
- vrf = vrf_lookup_by_name(vrfname);
- if (!vrf) {
- zlog_warn("%s: VRF %s doesn't exist", __func__,
- vrfname);
- return NB_ERR_VALIDATION;
- }
- if (vrf->vrf_id == VRF_UNKNOWN) {
- zlog_warn("%s: VRF %s is not active", __func__,
- vrf->name);
- return NB_ERR_VALIDATION;
- }
-
- /* if VRF is netns or not yet known - init for instance
- * then assumption is that passed config is exact
- * then the user intent was not to use an other iface
- */
- if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
- ifp = if_lookup_by_name_all_vrf(ifname);
- if (ifp && ifp->vrf_id != vrf->vrf_id) {
- zlog_warn(
- "%s: interface %s already exists in another VRF",
- __func__, ifp->name);
- return NB_ERR_VALIDATION;
- }
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- vrf = vrf_lookup_by_name(vrfname);
- assert(vrf);
- ifp = if_get_by_name(ifname, vrf->vrf_id);
+ ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname);
ifp->configured = true;
nb_running_set_entry(args->dnode, ifp);
@@ -1488,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args)
assert(vrf);
pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
} else {
- vrf = vrf_lookup_by_id(pif->vrf_id);
+ vrf = pif->vrf;
pif = RB_NEXT(if_name_head, pif);
/* if no more interfaces, switch to next vrf */
while (pif == NULL) {
@@ -1506,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args)
{
const struct interface *ifp = args->list_entry;
- struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
- assert(vrf);
-
args->keys->num = 2;
strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0]));
- strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1]));
+ strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1]));
return NB_OK;
}
diff --git a/lib/if.h b/lib/if.h
index 59e75d8b68..1125acd204 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -293,6 +293,8 @@ struct interface {
#endif /* HAVE_NET_RT_IFLIST */
struct route_node *node;
+
+ struct vrf *vrf;
vrf_id_t vrf_id;
/*
@@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2);
*/
extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
-/* Create new interface, adds to name list only */
-extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id);
-
-/* Create new interface, adds to index list only */
-extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);
extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex,
vrf_id_t vrf_id);
@@ -532,13 +529,11 @@ struct vrf;
extern struct interface *if_lookup_by_name_all_vrf(const char *ifname);
extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf);
extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id);
-extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id);
-extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id);
+extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id,
+ const char *vrf_name);
/* Sets the index and adds to index list */
extern int if_set_index(struct interface *ifp, ifindex_t ifindex);
-/* Sets the name and adds to name list */
-extern void if_set_name(struct interface *ifp, const char *name);
/* Delete the interface, but do not free the structure, and leave it in the
interface list. It is often advisable to leave the pseudo interface
diff --git a/lib/vrf.c b/lib/vrf.c
index 198d5253c8..6bc10b8cfd 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf)
if (vrf_is_enabled(vrf))
vrf_disable(vrf);
+ if (vrf->vrf_id != VRF_UNKNOWN) {
+ RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
+ vrf->vrf_id = VRF_UNKNOWN;
+ }
+
/* If the VRF is user configured, it'll stick around, just remove
* the ID mapping. Interfaces assigned to this VRF should've been
* removed already as part of the VRF going down.
*/
if (vrf_is_user_cfged(vrf)) {
- if (vrf->vrf_id != VRF_UNKNOWN) {
- /* Delete any VRF interfaces - should be only
- * the VRF itself, other interfaces should've
- * been moved out of the VRF.
- */
- if_terminate(vrf);
- RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
- vrf->vrf_id = VRF_UNKNOWN;
- }
vrf->ns_ctxt = NULL;
return;
}
+ /* Do not delete the VRF if it has interfaces configured in it. */
+ if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
+ return;
+
if (vrf_master.vrf_delete_hook)
(*vrf_master.vrf_delete_hook)(vrf);
QOBJ_UNREG(vrf);
- if_terminate(vrf);
- if (vrf->vrf_id != VRF_UNKNOWN)
- RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
if (vrf->name[0] != '\0')
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
@@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf)
{
/* Clear configured flag and invoke delete. */
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
+ if_terminate(vrf);
vrf_delete(vrf);
}
diff --git a/lib/zclient.c b/lib/zclient.c
index d639fa84b8..eea118738c 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2164,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id)
struct interface *ifp;
char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
struct stream *s = zclient->ibuf;
+ struct vrf *vrf;
/* Read interface name. */
STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
/* Lookup/create interface by name. */
- if (!vrf_get(vrf_id, NULL)) {
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf) {
zlog_debug(
"Rx'd interface add from Zebra, but VRF %u does not exist",
vrf_id);
return -1;
}
- ifp = if_get_by_name(ifname_tmp, vrf_id);
+ ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name);
zebra_interface_if_set_value(s, ifp);
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index f3e8127a80..a9b4c7756c 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -106,8 +106,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
return 0;
}
-static void ospf6_abr_delete_route(struct ospf6_route *range,
- struct ospf6_route *summary,
+static void ospf6_abr_delete_route(struct ospf6_route *summary,
struct ospf6_route_table *summary_table,
struct ospf6_lsa *old)
{
@@ -385,8 +384,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"The range is not active. withdraw");
- ospf6_abr_delete_route(route, summary,
- summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table,
+ old);
}
} else if (old) {
ospf6_route_remove(summary, summary_table);
@@ -400,7 +399,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"Area has been stubbed, purge Inter-Router LSA");
- ospf6_abr_delete_route(route, summary, summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -409,7 +408,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug("Area has been stubbed, purge prefix LSA");
- ospf6_abr_delete_route(route, summary, summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -444,8 +443,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"This is the secondary path to the ASBR, ignore");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -475,8 +473,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"Suppressed by range %pFX of area %s",
&range->prefix, route_area->name);
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
}
@@ -488,8 +485,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"This is the range with DoNotAdvertise set. ignore");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -497,8 +493,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
if (is_debug)
zlog_debug("The range is not active. withdraw");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
}
@@ -608,10 +603,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
struct ospf6_area *oa;
struct ospf6_route *range;
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
for (range = ospf6_route_head(oa->range_table); range;
range = ospf6_route_next(range))
OSPF6_ABR_RANGE_CLEAR_COST(range);
+ for (range = ospf6_route_head(oa->nssa_range_table); range;
+ range = ospf6_route_next(range))
+ OSPF6_ABR_RANGE_CLEAR_COST(range);
+ }
}
static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
@@ -622,10 +621,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
ro = ospf6_route_match_next(&range->prefix, ro)) {
- if (ro->path.area_id == range->path.area_id
- && (ro->path.type == OSPF6_PATH_TYPE_INTRA)
- && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
- cost = MAX(cost, ro->path.cost);
+ if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
+ continue;
+ if (ro->path.area_id != range->path.area_id)
+ continue;
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
+ && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
+ && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
+ continue;
+ if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
+ && ro->path.type != OSPF6_PATH_TYPE_INTRA)
+ continue;
+
+ cost = MAX(cost, ro->path.cost);
}
return cost;
@@ -674,6 +682,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
int summary_orig = 0;
assert(range->type == OSPF6_DEST_TYPE_RANGE);
+ oa = ospf6_area_lookup(range->path.area_id, ospf6);
+ assert(oa);
/* update range's cost and active flag */
cost = ospf6_abr_range_compute_cost(range, ospf6);
@@ -696,34 +706,49 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
* if there
* were active ranges.
*/
+ if (!ospf6_abr_range_summary_needs_update(range, cost))
+ return;
- if (ospf6_abr_range_summary_needs_update(range, cost)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("%s: range %pFX update", __func__,
- &range->prefix);
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("%s: range %pFX update", __func__, &range->prefix);
+
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
+ && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
+ ospf6_nssa_lsa_originate(range, oa, true);
+ summary_orig = 1;
+ } else {
+ struct ospf6_lsa *lsa;
+
+ lsa = ospf6_lsdb_lookup(range->path.origin.type,
+ range->path.origin.id,
+ ospf6->router_id, oa->lsdb);
+ if (lsa)
+ ospf6_lsa_premature_aging(lsa);
+ }
+ } else {
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
summary_orig +=
ospf6_abr_originate_summary_to_area(range, oa);
+ }
+ }
- if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
- && summary_orig) {
- if (!CHECK_FLAG(range->flag,
- OSPF6_ROUTE_BLACKHOLE_ADDED)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("Add discard route");
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
+ && summary_orig) {
+ if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("Add discard route");
- ospf6_zebra_add_discard(range, ospf6);
- }
- } else {
- /* Summary removed or no summary generated as no
- * specifics exist */
- if (CHECK_FLAG(range->flag,
- OSPF6_ROUTE_BLACKHOLE_ADDED)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("Delete discard route");
+ ospf6_zebra_add_discard(range, ospf6);
+ }
+ } else {
+ /* Summary removed or no summary generated as no
+ * specifics exist */
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("Delete discard route");
- ospf6_zebra_delete_discard(range, ospf6);
- }
+ ospf6_zebra_delete_discard(range, ospf6);
}
}
}
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 999266b8d1..996892c49c 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -306,7 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
oa->range_table->scope = oa;
- bf_init(oa->range_table->idspace, 32);
+ oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
+ oa->nssa_range_table->scope = oa;
oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
oa->summary_prefix->scope = oa;
oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
@@ -361,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa)
ospf6_route_table_delete(oa->route_table);
ospf6_route_table_delete(oa->range_table);
+ ospf6_route_table_delete(oa->nssa_range_table);
ospf6_route_table_delete(oa->summary_prefix);
ospf6_route_table_delete(oa->summary_router);
@@ -576,8 +578,6 @@ DEFUN (area_range,
range->path.u.cost_config = cost;
- zlog_debug("%s: for prefix %s, flag = %x", __func__,
- argv[idx_ipv6_prefixlen]->arg, range->flag);
if (range->rnode == NULL) {
ospf6_route_add(range, oa->range_table);
}
@@ -694,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
vty_out(vty, " no-summary");
vty_out(vty, "\n");
}
+ for (range = ospf6_route_head(oa->nssa_range_table); range;
+ range = ospf6_route_next(range)) {
+ vty_out(vty, " area %s nssa range %pFX", oa->name,
+ &range->prefix);
+
+ if (CHECK_FLAG(range->flag,
+ OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
+ vty_out(vty, " not-advertise");
+ } else {
+ if (range->path.u.cost_config
+ != OSPF_AREA_RANGE_COST_UNSPEC)
+ vty_out(vty, " cost %u",
+ range->path.u.cost_config);
+ }
+ vty_out(vty, "\n");
+ }
if (PREFIX_NAME_IN(oa))
vty_out(vty, " area %s filter-list prefix %s in\n",
oa->name, PREFIX_NAME_IN(oa));
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index 77cbad8b9e..905fbac949 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -46,6 +46,7 @@ struct ospf6_area {
/* Summary routes to be originated (includes Configured Address Ranges)
*/
struct ospf6_route_table *range_table;
+ struct ospf6_route_table *nssa_range_table;
struct ospf6_route_table *summary_prefix;
struct ospf6_route_table *summary_router;
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 150903a56a..6e00bd766f 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -266,10 +266,14 @@ void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa)
/* RFC2328 section 13.2 Installing LSAs in the database */
void ospf6_install_lsa(struct ospf6_lsa *lsa)
{
+ struct ospf6 *ospf6;
struct timeval now;
struct ospf6_lsa *old;
struct ospf6_area *area = NULL;
+ ospf6 = ospf6_get_by_lsdb(lsa);
+ assert(ospf6);
+
/* Remove the old instance from all neighbors' Link state
retransmission list (RFC2328 13.2 last paragraph) */
old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
@@ -330,20 +334,14 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
&& !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) {
/* check if it is new lsa ? or existing lsa got modified ?*/
- if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) {
- struct ospf6 *ospf6;
-
- ospf6 = ospf6_get_by_lsdb(lsa);
-
- assert(ospf6);
-
+ if (!old || OSPF6_LSA_IS_CHANGED(old, lsa))
ospf6_helper_handle_topo_chg(ospf6, lsa);
- }
}
ospf6_lsdb_add(lsa, lsa->lsdb);
- if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
+ if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
+ && lsa->header->adv_router != ospf6->router_id) {
area = OSPF6_AREA(lsa->lsdb->data);
ospf6_translated_nssa_refresh(area, lsa, NULL);
ospf6_schedule_abr_task(area->ospf6);
diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c
index 40893ed998..c3e6f62f06 100644
--- a/ospf6d/ospf6_gr.c
+++ b/ospf6d/ospf6_gr.c
@@ -58,7 +58,7 @@ static int ospf6_gr_lsa_originate(struct ospf6_interface *oi)
char buffer[OSPF6_MAX_LSASIZE];
if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
- zlog_debug("Originate Link-LSA for Interface %s",
+ zlog_debug("Originate Grace-LSA for Interface %s",
oi->interface->name);
/* prepare buffer */
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 9d73740819..64992bbcee 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1241,7 +1241,6 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
{
struct listnode *n;
struct connected *c;
- struct in6_addr *l = (struct in6_addr *)NULL;
/* for each connected address */
for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
@@ -1250,9 +1249,10 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
continue;
if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
- l = &c->address->u.prefix6;
+ return &c->address->u.prefix6;
}
- return l;
+
+ return NULL;
}
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index f406e828e1..77f0f8f4e5 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -1070,7 +1070,7 @@ DEFPY (debug_ospf6_lsa_aggregation,
DEFUN (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_cmd,
- "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
+ "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
@@ -1079,6 +1079,7 @@ DEFUN (debug_ospf6_lsa_type,
"Display Inter-Area-Prefix LSAs\n"
"Display Inter-Router LSAs\n"
"Display As-External LSAs\n"
+ "Display NSSA LSAs\n"
"Display Link LSAs\n"
"Display Intra-Area-Prefix LSAs\n"
"Display LSAs of unknown origin\n"
@@ -1122,7 +1123,7 @@ DEFUN (debug_ospf6_lsa_type,
DEFUN (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_cmd,
- "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
+ "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
NO_STR
DEBUG_STR
OSPF6_STR
@@ -1132,6 +1133,7 @@ DEFUN (no_debug_ospf6_lsa_type,
"Display Inter-Area-Prefix LSAs\n"
"Display Inter-Router LSAs\n"
"Display As-External LSAs\n"
+ "Display NSSA LSAs\n"
"Display Link LSAs\n"
"Display Intra-Area-Prefix LSAs\n"
"Display LSAs of unknown origin\n"
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index 2316040694..c0d3cc149b 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -87,11 +87,6 @@
#define OSPF6_SCOPE_AS 0x4000
#define OSPF6_SCOPE_RESERVED 0x6000
-/* AS-external-LSA refresh method. */
-#define LSA_REFRESH_IF_CHANGED 0
-#define LSA_REFRESH_FORCE 1
-
-
/* XXX U-bit handling should be treated here */
#define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK)
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 6f2795a56d..36948dc0a7 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -48,7 +48,7 @@
#include "ospf6_gr.h"
#include "lib/json.h"
-DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
DEFINE_HOOK(ospf6_neighbor_change,
(struct ospf6_neighbor * on, int state, int next_state),
diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c
index c2e9b7f28a..84f014d680 100644
--- a/ospf6d/ospf6_nssa.c
+++ b/ospf6d/ospf6_nssa.c
@@ -49,6 +49,9 @@
#include "ospf6_asbr.h"
#include "ospf6d.h"
#include "ospf6_nssa.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "ospf6d/ospf6_nssa_clippy.c"
+#endif
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
unsigned char config_debug_ospf6_nssa = 0;
@@ -262,22 +265,20 @@ static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
{
struct ospf6_area *area;
struct ospf6_route *range;
- struct listnode *node, *nnode;
+ struct listnode *node;
if (IS_OSPF6_DEBUG_ABR)
zlog_debug("ospf6_abr_announce_aggregates(): Start");
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
- for (range = ospf6_route_head(area->range_table); range;
- range = ospf6_route_next(range))
- ospf6_abr_range_update(range, ospf6);
- }
-
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
if (IS_OSPF6_DEBUG_ABR)
zlog_debug(
"ospf_abr_announce_aggregates(): looking at area %pI4",
&area->area_id);
+
+ for (range = ospf6_route_head(area->range_table); range;
+ range = ospf6_route_next(range))
+ ospf6_abr_range_update(range, ospf6);
}
if (IS_OSPF6_DEBUG_ABR)
@@ -381,22 +382,18 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
{
struct ospf6_lsa *lsa;
uint16_t type;
- struct ospf6_area *oa;
- struct listnode *node;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_unapprove_translates(): Start");
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
- for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
- for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
- if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
- SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "%s : approved unset on link id %pI4",
- __func__, &lsa->header->id);
- }
+ for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
+ if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
+ SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
+ if (IS_OSPF6_DEBUG_NSSA)
+ zlog_debug(
+ "%s : approved unset on link id %pI4",
+ __func__, &lsa->header->id);
}
}
@@ -408,17 +405,17 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
struct ospf6_lsa *type7)
{
- char *buffer;
+ char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa *lsa;
struct ospf6_as_external_lsa *ext, *extnew;
struct ospf6_lsa_header *lsa_header;
caddr_t old_ptr, new_ptr;
struct ospf6_as_external_lsa *nssa;
struct prefix prefix;
- struct ospf6_route *match;
struct ospf6 *ospf6 = area->ospf6;
ptrdiff_t tag_offset = 0;
route_tag_t network_order;
+ struct ospf6_route *range;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Start", __func__);
@@ -430,7 +427,27 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
return NULL;
}
- buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE);
+ /* find the translated Type-5 for this Type-7 */
+ nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ type7->header);
+ prefix.family = AF_INET6;
+ prefix.prefixlen = nssa->prefix.prefix_length;
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
+
+ /* Check if the Type-7 LSA should be suppressed by aggregation. */
+ range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table);
+ if (range && !prefix_same(&prefix, &range->prefix)
+ && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
+ if (IS_OSPF6_DEBUG_NSSA)
+ zlog_debug(
+ "%s: LSA %s suppressed by range %pFX of area %s",
+ __func__, type7->name, &range->prefix,
+ area->name);
+ return NULL;
+ }
+
+ /* prepare buffer */
+ memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
extnew = (struct ospf6_as_external_lsa
*)((caddr_t)lsa_header
@@ -445,23 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
- /* find the translated Type-5 for this Type-7 */
- nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
- type7->header);
-
- prefix.family = AF_INET6;
- prefix.prefixlen = nssa->prefix.prefix_length;
- ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
-
- /* Find the LSA from the external route */
- match = ospf6_route_lookup(&prefix, area->route_table);
- if (match == NULL) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("%s : no matching route %pFX", __func__,
- &prefix);
- return NULL;
- }
-
/* set Prefix */
memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
ospf6_prefix_apply_mask(&extnew->prefix);
@@ -542,7 +542,6 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
struct ospf6_lsa *type5)
{
struct ospf6_lsa *new = NULL;
- struct ospf6_as_external_lsa *ext_lsa;
struct prefix prefix;
struct ospf6 *ospf6 = area->ospf6;
@@ -554,27 +553,27 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
/* Find the AS external LSA */
if (type5 == NULL) {
+ struct ospf6_as_external_lsa *ext_lsa;
+ struct ospf6_route *match;
+
+ /* Find the AS external LSA from Type-7 LSA */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
- "%s: No translated Type-5 found for Type-7 with Id %pI4",
- __func__, &type7->header->id);
+ "%s: try to find translated Type-5 LSA for %s",
+ __func__, type7->name);
- /* find the translated Type-5 for this Type-7 */
ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
type7->header);
-
prefix.family = AF_INET6;
prefix.prefixlen = ext_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
&ext_lsa->prefix);
- /* Find the AS external LSA from Type-7 LSA */
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("%s: try to find external LSA id %d",
- __func__, type7->external_lsa_id);
- type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
- type7->external_lsa_id,
- ospf6->router_id, ospf6->lsdb);
+ match = ospf6_route_lookup(&prefix, ospf6->external_table);
+ if (match)
+ type5 = ospf6_lsdb_lookup(
+ OSPF6_LSTYPE_AS_EXTERNAL, match->path.origin.id,
+ ospf6->router_id, ospf6->lsdb);
}
if (type5) {
@@ -602,6 +601,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
__func__, &type7->header->id);
return NULL;
}
+ UNSET_FLAG(new->flag, OSPF6_LSA_UNAPPROVED);
}
if (IS_OSPF6_DEBUG_NSSA)
@@ -610,32 +610,11 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
return new;
}
-/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
-struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa,
- struct ospf6_lsa *type7)
-{
- struct ospf6_lsa *new;
-
- if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7)
- return NULL;
-
- if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "%s : Could not translate Type-7, Id %pI4, to Type-5",
- __func__, &type7->header->id);
- return NULL;
- }
-
- return new;
-}
-
-int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
+static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
{
/* Incoming Type-7 or later aggregated Type-7
*
* LSA is skipped if P-bit is off.
- * LSA is aggregated if within range.
*
* The Type-7 is translated, Installed/Approved as a Type-5 into
* global LSDB, then Flooded through AS
@@ -659,7 +638,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
zlog_debug(
"%s : LSA Id %pI4, P-bit off, NO Translation",
__func__, &lsa->header->id);
- return 1;
+ return;
}
if (IS_OSPF6_DEBUG_NSSA)
@@ -676,7 +655,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
zlog_debug(
"%s : LSA Id %pI4, Forward address is 0, NO Translation",
__func__, &lsa->header->id);
- return 1;
+ return;
}
/* Find the existing AS-External LSA for this prefix */
@@ -687,23 +666,13 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
ospf6->lsdb);
}
- /* Check Type 5 LSA using the matching external ID */
- if (old == NULL) {
- old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
- lsa->external_lsa_id, ospf6->router_id,
- ospf6->lsdb);
+ if (OSPF6_LSA_IS_MAXAGE(lsa)) {
+ if (old)
+ ospf6_lsa_premature_aging(old);
+ return;
}
if (old) {
- /* Do not continue if type 5 LSA not approved */
- if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "%s : LSA Id %pI4 type 5 is not approved",
- __func__, &old->header->id);
- return 1;
- }
-
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : found old translated LSA Id %pI4, refreshing",
@@ -722,16 +691,14 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
* originate translated LSA
*/
- if (ospf6_translated_nssa_originate(area, lsa) == NULL) {
+ if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : Could not translate Type-7 for %pI4 to Type-5",
__func__, &lsa->header->id);
- return 1;
+ return;
}
}
-
- return 0;
}
static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
@@ -751,6 +718,8 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
zlog_debug("%s : Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
+ if (!IS_AREA_NSSA(oa))
+ continue;
/* skip if not translator */
if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
@@ -760,13 +729,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
continue;
}
- /* skip if not Nssa Area */
- if (!IS_AREA_NSSA(oa)) {
- zlog_debug("%s area %pI4 Flag %x", __func__,
- &oa->area_id, oa->flag);
- continue;
- }
-
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : looking at area %pI4", __func__,
&oa->area_id);
@@ -784,71 +746,30 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
zlog_debug("%s : Stop", __func__);
}
-/* Generate translated type-5 LSA from the configured area ranges*/
-static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6)
-{
- struct listnode *node, *nnode;
- struct ospf6_area *oa;
- struct ospf6_route *range;
- struct ospf6_lsa *lsa;
-
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
- for (range = ospf6_route_head(oa->range_table); range;
- range = ospf6_route_next(range)) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "Translating range %pFX of area %pI4",
- &range->prefix, &oa->area_id);
- if (CHECK_FLAG(range->flag,
- OSPF6_ROUTE_DO_NOT_ADVERTISE))
- continue;
-
- /* Find the NSSA LSA from the route */
- /* Generate and flood external LSA */
- lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7,
- range->path.origin.id,
- ospf6->router_id, oa->lsdb);
- if (lsa)
- ospf6_abr_translate_nssa(oa, lsa);
- }
- }
-}
-
static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
{
struct listnode *node;
struct ospf6_area *area;
+ struct ospf6_route *range;
if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("%s : Start", __func__);
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
continue;
if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("%s : looking at area %pI4", __func__,
+ zlog_debug("%s: looking at area %pI4", __func__,
&area->area_id);
- ospf6_abr_translate_nssa_range(ospf6);
+ for (range = ospf6_route_head(area->nssa_range_table); range;
+ range = ospf6_route_next(range))
+ ospf6_abr_range_update(range, ospf6);
}
if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("%s : Stop", __func__);
-}
-
-/*Flood max age LSA's for the unapproved LSA's */
-static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa)
-{
- if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
- && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
- zlog_debug("%s : removing unapproved translates, lsa : %s",
- __func__, lsa->name);
-
- /* FLUSH THROUGHOUT AS */
- ospf6_lsa_premature_aging(lsa);
- }
- return 0;
+ zlog_debug("%s: Stop", __func__);
}
static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
@@ -862,8 +783,16 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
zlog_debug("ospf6_abr_remove_unapproved_translates(): Start");
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
- for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa))
- ospf6_abr_remove_unapproved_translates_apply(lsa);
+ for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
+ if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
+ && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
+ zlog_debug(
+ "%s : removing unapproved translates, lsa : %s",
+ __func__, lsa->name);
+
+ ospf6_lsa_premature_aging(lsa);
+ }
+ }
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
@@ -948,11 +877,6 @@ void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
{
- /* called only if any_nssa */
- struct ospf6_route *range;
- struct ospf6_area *area;
- struct listnode *node, *nnode;
-
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("Check for NSSA-ABR Tasks():");
@@ -978,10 +902,10 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
ospf6_abr_unapprove_translates(ospf6);
- /* RESET all Ranges in every Area, same as summaries */
+ /* Originate Type-7 aggregates */
if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates");
- ospf6_abr_range_reset_cost(ospf6);
+ zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
+ ospf6_abr_send_nssa_aggregates(ospf6);
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
* Aggregate as Type-7
@@ -991,32 +915,12 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
zlog_debug("ospf6_abr_nssa_task(): process translates");
ospf6_abr_process_nssa_translates(ospf6);
- /* Translate/Send any "ranged" aggregates, and also 5-Install and
- * Approve
- * Scan Type-7's for aggregates, translate to Type-5's,
- * Install/Flood/Approve
- */
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
- ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */
-
/* Flush any unapproved previous translates from Global Data Base */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"ospf6_abr_nssa_task(): remove unapproved translates");
ospf6_abr_remove_unapproved_translates(ospf6);
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
- for (range = ospf6_route_head(area->range_table); range;
- range = ospf6_route_next(range)) {
- if (CHECK_FLAG(range->flag,
- OSPF6_ROUTE_DO_NOT_ADVERTISE))
- ospf6_zebra_delete_discard(range, ospf6);
- else
- ospf6_zebra_add_discard(range, ospf6);
- }
- }
-
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_nssa_task(): Stop");
}
@@ -1063,106 +967,6 @@ int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
return 1;
}
-static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type,
- unsigned short instance, int force)
-{
- struct ospf6_route *route;
- struct ospf6_external_info *info;
- struct ospf6_lsa *lsa;
-
- if (type == ZEBRA_ROUTE_MAX)
- return;
-
- for (route = ospf6_route_head(ospf6->external_table); route;
- route = ospf6_route_next(route)) {
- info = route->route_option;
-
- /* Find the external LSA in the database */
- if (!is_default_prefix(&route->prefix)) {
- lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
- htonl(info->id),
- ospf6->router_id, ospf6->lsdb);
-
- if (lsa) {
- THREAD_OFF(lsa->refresh);
-
- /* LSA is maxage, immediate refresh */
- if (OSPF6_LSA_IS_MAXAGE(lsa))
- ospf6_flood(NULL, lsa);
- else
- thread_add_timer(master,
- ospf6_lsa_refresh, lsa,
- OSPF_LS_REFRESH_TIME,
- &lsa->refresh);
- } else {
- /* LSA not found in the database
- * Verify and originate external LSA
- */
- if (ospf6_redistribute_check(ospf6, route,
- type))
- ospf6_as_external_lsa_originate(route,
- ospf6);
- }
- }
- }
-}
-
-/* Refresh default route */
-static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6)
-{
- struct ospf6_route *route;
- struct ospf6_external_info *info;
- struct ospf6_lsa *lsa;
-
- for (route = ospf6_route_head(ospf6->external_table); route;
- route = ospf6_route_next(route)) {
- if (is_default_prefix(&route->prefix)) {
- info = route->route_option;
- lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
- htonl(info->id),
- ospf6->router_id, ospf6->lsdb);
-
- if (lsa) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
- (void *)lsa);
- if (OSPF6_LSA_IS_MAXAGE(lsa))
- ospf6_flood(NULL, lsa);
- else
- thread_add_timer(master,
- ospf6_lsa_refresh, lsa,
- OSPF_LS_REFRESH_TIME,
- &lsa->refresh);
- } else if (!lsa) {
- if (IS_OSPF6_DEBUG_NSSA)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
- ospf6_as_external_lsa_originate(route, ospf6);
- }
- }
- }
-}
-
-/* If there's redistribution configured, we need to refresh external
- * LSAs in order to install Type-7 and flood to all NSSA Areas
- */
-void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6)
-{
- int type;
- struct ospf6_redist *red;
-
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
- red = ospf6_redist_lookup(ospf6, type, 0);
- if (!red)
- return;
-
- ospf6_external_lsa_refresh_type(ospf6, type, red->instance,
- LSA_REFRESH_IF_CHANGED);
- }
- ospf6_external_lsa_refresh_default(ospf6);
-}
-
/* This function performs ABR related processing */
static int ospf6_abr_task_timer(struct thread *thread)
{
@@ -1176,7 +980,6 @@ static int ospf6_abr_task_timer(struct thread *thread)
ospf6_abr_task(ospf6);
/* if nssa-abr, then scan Type-7 LSDB */
ospf6_abr_nssa_task(ospf6);
- ospf6_asbr_nssa_redist_task(ospf6);
return 0;
}
@@ -1337,6 +1140,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("area %s nssa reset", area->name);
+
+ /* Clear the table of NSSA ranges. */
+ ospf6_route_table_delete(area->nssa_range_table);
+ area->nssa_range_table =
+ OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
+ area->nssa_range_table->scope = area;
+
ospf6_area_nssa_update(area);
}
@@ -1350,10 +1160,14 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
struct ospf6_interface *oi;
for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
- if (if_is_operative(oi->interface))
- if (oi->area && IS_AREA_NSSA(oi->area))
- return ospf6_interface_get_global_address(
- oi->interface);
+ struct in6_addr *addr;
+
+ if (!if_is_operative(oi->interface))
+ continue;
+
+ addr = ospf6_interface_get_global_address(oi->interface);
+ if (addr)
+ return addr;
}
return NULL;
}
@@ -1463,17 +1277,119 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : start", __func__);
+ if (!ospf6_check_and_set_router_abr(ospf6))
+ return;
+
type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
lsa->external_lsa_id, ospf6->router_id,
ospf6->lsdb);
-
- if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) {
+ if (!type5) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Originating type5 LSA", __func__);
ospf6_lsa_translated_nssa_new(area, lsa);
}
}
+DEFPY (area_nssa_range,
+ area_nssa_range_cmd,
+ "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
+ "OSPF6 area parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as nssa\n"
+ "Configured address range\n"
+ "Specify IPv6 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\n")
+{
+ struct ospf6_area *oa;
+ struct ospf6_route *range;
+
+ VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+
+ OSPF6_CMD_AREA_GET(area, oa, ospf6);
+
+ if (!IS_AREA_NSSA(oa)) {
+ vty_out(vty, "%% First configure %s as an NSSA area\n", area);
+ return CMD_WARNING;
+ }
+
+ range = ospf6_route_lookup((struct prefix *)prefix,
+ oa->nssa_range_table);
+ if (range == NULL) {
+ range = ospf6_route_create(ospf6);
+ range->type = OSPF6_DEST_TYPE_RANGE;
+ SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE);
+ prefix_copy(&range->prefix, prefix);
+ range->path.area_id = oa->area_id;
+ range->path.metric_type = 2;
+ range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
+ range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7);
+ range->path.origin.id = htonl(ospf6->external_id++);
+ range->path.origin.adv_router = ospf6->router_id;
+ ospf6_route_add(range, oa->nssa_range_table);
+ }
+
+ /* process "not-advertise" */
+ if (not_adv)
+ SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+ else
+ UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+
+ /* process "cost" */
+ if (!cost_str)
+ cost = OSPF_AREA_RANGE_COST_UNSPEC;
+ range->path.u.cost_config = cost;
+
+ /* Redo summaries if required */
+ if (ospf6_check_and_set_router_abr(ospf6))
+ ospf6_schedule_abr_task(ospf6);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_area_nssa_range,
+ no_area_nssa_range_cmd,
+ "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
+ NO_STR
+ "OSPF6 area parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as nssa\n"
+ "Configured address range\n"
+ "Specify IPv6 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\n")
+{
+ struct ospf6_area *oa;
+ struct ospf6_route *range;
+
+ VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+
+ OSPF6_CMD_AREA_GET(area, oa, ospf6);
+
+ range = ospf6_route_lookup((struct prefix *)prefix,
+ oa->nssa_range_table);
+ if (range == NULL) {
+ vty_out(vty, "%% range %s does not exists.\n", prefix_str);
+ return CMD_SUCCESS;
+ }
+
+ if (ospf6_check_and_set_router_abr(oa->ospf6)) {
+ /* Blow away the aggregated LSA and route */
+ SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
+
+ /* Redo summaries if required */
+ thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
+ }
+
+ ospf6_route_remove(range, oa->nssa_range_table);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
"debug ospf6 nssa",
DEBUG_STR
@@ -1503,6 +1419,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty)
void install_element_ospf6_debug_nssa(void)
{
+ install_element(OSPF6_NODE, &area_nssa_range_cmd);
+ install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
+
install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
diff --git a/ospf6d/ospf6_nssa.h b/ospf6d/ospf6_nssa.h
index 99cb04c003..02234cc8bd 100644
--- a/ospf6d/ospf6_nssa.h
+++ b/ospf6d/ospf6_nssa.h
@@ -55,8 +55,6 @@ extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p);
extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa,
struct ospf6_lsa *type7,
struct ospf6_lsa *type5);
-extern struct ospf6_lsa *
-ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7);
extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6);
@@ -69,8 +67,6 @@ extern void install_element_ospf6_debug_nssa(void);
extern void ospf6_abr_nssa_type_7_defaults(struct ospf6 *osof6);
int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
int type);
-extern int ospf6_abr_translate_nssa(struct ospf6_area *area,
- struct ospf6_lsa *lsa);
extern void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
struct ospf6_lsa *lsa);
extern void ospf6_abr_nssa_check_status(struct ospf6 *ospf6);
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 4b87c4cf30..a4ed99ea2d 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -1098,7 +1098,6 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t)
void ospf6_route_table_delete(struct ospf6_route_table *table)
{
ospf6_route_remove_all(table);
- bf_free(table->idspace);
route_table_finish(table->table);
XFREE(MTYPE_OSPF6_ROUTE_TABLE, table);
}
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index e29439b95e..fd8b6a9c1d 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -186,7 +186,7 @@ struct ospf6_route {
struct timeval changed;
/* flag */
- uint8_t flag;
+ uint16_t flag;
/* Prefix Options */
uint8_t prefix_options;
@@ -221,14 +221,15 @@ struct ospf6_route {
#define OSPF6_DEST_TYPE_RANGE 5
#define OSPF6_DEST_TYPE_MAX 6
-#define OSPF6_ROUTE_CHANGE 0x01
-#define OSPF6_ROUTE_ADD 0x02
-#define OSPF6_ROUTE_REMOVE 0x04
-#define OSPF6_ROUTE_BEST 0x08
-#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10
-#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20
-#define OSPF6_ROUTE_WAS_REMOVED 0x40
-#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80
+#define OSPF6_ROUTE_CHANGE 0x0001
+#define OSPF6_ROUTE_ADD 0x0002
+#define OSPF6_ROUTE_REMOVE 0x0004
+#define OSPF6_ROUTE_BEST 0x0008
+#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010
+#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020
+#define OSPF6_ROUTE_WAS_REMOVED 0x0040
+#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080
+#define OSPF6_ROUTE_NSSA_RANGE 0x0100
struct ospf6;
struct ospf6_route_table {
@@ -241,8 +242,6 @@ struct ospf6_route_table {
uint32_t count;
- bitfield_t idspace;
-
/* hooks */
void (*hook_add)(struct ospf6_route *);
void (*hook_change)(struct ospf6_route *);
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 9e3bb4895a..7e9ed4160d 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -1032,7 +1032,6 @@ DEFUN_HIDDEN (ospf6_interface_area,
struct ospf6_area *oa;
struct ospf6_interface *oi;
struct interface *ifp;
- vrf_id_t vrf_id = VRF_DEFAULT;
uint32_t area_id;
int format;
@@ -1041,11 +1040,8 @@ DEFUN_HIDDEN (ospf6_interface_area,
vty_out(vty,
"Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
- if (ospf6->vrf_id != VRF_UNKNOWN)
- vrf_id = ospf6->vrf_id;
-
/* find/create ospf6 interface */
- ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
+ ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
@@ -1107,18 +1103,14 @@ DEFUN_HIDDEN (no_ospf6_interface_area,
struct ospf6_area *oa;
struct interface *ifp;
uint32_t area_id;
- vrf_id_t vrf_id = VRF_DEFAULT;
vty_out(vty,
"This command is deprecated, because it is not VRF-aware.\n");
vty_out(vty,
"Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
- if (ospf6->vrf_id != VRF_UNKNOWN)
- vrf_id = ospf6->vrf_id;
-
/* find/create ospf6 interface */
- ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
+ ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
if (ifp == NULL) {
vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am
index be626646a0..34aabc205b 100644
--- a/ospf6d/subdir.am
+++ b/ospf6d/subdir.am
@@ -99,6 +99,7 @@ clippy_scan += \
ospf6d/ospf6_lsa.c \
ospf6d/ospf6_gr_helper.c \
ospf6d/ospf6_gr.c \
+ ospf6d/ospf6_nssa.c \
ospf6d/ospf6_route.c \
# end
diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c
index 6a5c0bae98..8276ccb89c 100644
--- a/ospfd/ospf_gr.c
+++ b/ospfd/ospf_gr.c
@@ -150,7 +150,7 @@ static struct ospf_lsa *ospf_gr_lsa_new(struct ospf_interface *oi)
}
/* Originate and install Grace-LSA for a given interface. */
-static void ospf_gr_lsa_originate(struct ospf_interface *oi)
+static void ospf_gr_lsa_originate(struct ospf_interface *oi, bool maxage)
{
struct ospf_lsa *lsa, *old;
@@ -164,6 +164,9 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi)
return;
}
+ if (maxage)
+ lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
+
/* Find the old LSA and increase the seqno. */
old = ospf_gr_lsa_lookup(oi->ospf, oi->area);
if (old)
@@ -183,37 +186,6 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi)
ospf_flood_through_interface(oi, NULL, lsa);
}
-/* Flush a given self-originated Grace-LSA. */
-static struct ospf_lsa *ospf_gr_flush_grace_lsa(struct ospf_interface *oi,
- struct ospf_lsa *old)
-{
- struct ospf_lsa *lsa;
-
- if (ospf_interface_neighbor_count(oi) == 0)
- return NULL;
-
- if (IS_DEBUG_OSPF_GR)
- zlog_debug(
- "GR: flushing self-originated Grace-LSAs [interface %s]",
- oi->ifp->name);
-
- lsa = ospf_lsa_dup(old);
- lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
- lsa->data->ls_seqnum = lsa_seqnum_increment(lsa);
-
- /* Install updated LSA into LSDB. */
- if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) {
- zlog_warn("%s: ospf_lsa_install() failed", __func__);
- ospf_lsa_unlock(&lsa);
- return NULL;
- }
-
- /* Flood the LSA through out the interface */
- ospf_flood_through_interface(oi, NULL, lsa);
-
- return lsa;
-}
-
/* Flush all self-originated Grace-LSAs. */
static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
{
@@ -221,7 +193,6 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
struct listnode *anode;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
- struct ospf_lsa *lsa;
struct ospf_interface *oi;
struct listnode *inode;
@@ -230,15 +201,8 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
"GR: flushing self-originated Grace-LSAs [area %pI4]",
&area->area_id);
- lsa = ospf_gr_lsa_lookup(ospf, area);
- if (!lsa) {
- zlog_warn("%s: Grace-LSA not found [area %pI4]",
- __func__, &area->area_id);
- continue;
- }
-
for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi))
- ospf_gr_flush_grace_lsa(oi, lsa);
+ ospf_gr_lsa_originate(oi, true);
}
}
@@ -750,7 +714,7 @@ static void ospf_gr_prepare(void)
/* Send a Grace-LSA to all neighbors. */
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi))
- ospf_gr_lsa_originate(oi);
+ ospf_gr_lsa_originate(oi, false);
/* Record end of the grace period in non-volatile memory. */
ospf_gr_nvm_update(ospf);
@@ -770,6 +734,18 @@ DEFPY(graceful_restart_prepare, graceful_restart_prepare_cmd,
IP_STR
"Prepare to restart the OSPF process")
{
+ struct ospf *ospf;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
+ if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
+ vty_out(vty,
+ "%% Can't start graceful restart: opaque capability not enabled (VRF %s)\n\n",
+ ospf_get_name(ospf));
+ return CMD_WARNING;
+ }
+ }
+
ospf_gr_prepare();
return CMD_SUCCESS;
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 81cc346000..60e109ea80 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -915,9 +915,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
ospf->vrf_id);
snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count);
- vi = if_create_name(ifname, ospf->vrf_id);
+ vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name);
/*
- * if_create_name sets ZEBRA_INTERFACE_LINKDETECTION
+ * if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION
* virtual links don't need this.
*/
UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION);
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 4294c255af..ca4bb0a2b9 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -1096,39 +1096,41 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
zlog_debug(
"%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
__PRETTY_FUNCTION__);
-
- return;
- }
-
- /* If neighbor itself declares DR and no BDR exists,
- cause event BackupSeen */
- if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router))
- if (hello->bd_router.s_addr == INADDR_ANY
- && oi->state == ISM_Waiting)
+ } else {
+ /* If neighbor itself declares DR and no BDR exists,
+ cause event BackupSeen */
+ if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router))
+ if (hello->bd_router.s_addr == INADDR_ANY
+ && oi->state == ISM_Waiting)
+ OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen);
+
+ /* neighbor itself declares BDR. */
+ if (oi->state == ISM_Waiting
+ && IPV4_ADDR_SAME(&nbr->address.u.prefix4,
+ &hello->bd_router))
OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen);
- /* neighbor itself declares BDR. */
- if (oi->state == ISM_Waiting
- && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router))
- OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen);
-
- /* had not previously. */
- if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)
- && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router))
- || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router)
- && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->d_router)))
- OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
-
- /* had not previously. */
- if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router)
- && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router))
- || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->bd_router)
- && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->bd_router)))
- OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
-
- /* Neighbor priority check. */
- if (nbr->priority >= 0 && nbr->priority != hello->priority)
- OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
+ /* had not previously. */
+ if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)
+ && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router))
+ || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router)
+ && IPV4_ADDR_SAME(&nbr->address.u.prefix4,
+ &nbr->d_router)))
+ OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
+
+ /* had not previously. */
+ if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router)
+ && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router))
+ || (IPV4_ADDR_CMP(&nbr->address.u.prefix4,
+ &hello->bd_router)
+ && IPV4_ADDR_SAME(&nbr->address.u.prefix4,
+ &nbr->bd_router)))
+ OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
+
+ /* Neighbor priority check. */
+ if (nbr->priority >= 0 && nbr->priority != hello->priority)
+ OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange);
+ }
/* Set neighbor information. */
nbr->priority = hello->priority;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 9863a10115..64d3b7a028 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -445,7 +445,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr,
"Please, use \"ip ospf passive\" on an interface instead.\n");
if (ospf->vrf_id != VRF_UNKNOWN)
- ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id);
+ ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name);
if (ifp == NULL) {
vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg);
@@ -506,7 +506,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface,
"Please, use \"no ip ospf passive\" on an interface instead.\n");
if (ospf->vrf_id != VRF_UNKNOWN)
- ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id);
+ ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name);
if (ifp == NULL) {
vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index eb19cf4ddf..5e311d101a 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1482,7 +1482,8 @@ void pim_if_create_pimreg(struct pim_instance *pim)
snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
pim->vrf->data.l.table_id);
- pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id);
+ pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id,
+ pim->vrf->name);
pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
pim_if_new(pim->regiface, false, false, true,
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 066c45f55c..a7286d1878 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -717,6 +717,7 @@ fi
%files pythontools
%{_sbindir}/generate_support_bundle.py
%{_sbindir}/frr-reload.py
+%{_sbindir}/frr_babeltrace.py
%if 0%{?rhel} > 7 || 0%{?fedora} > 29
%{_sbindir}/__pycache__/*
%else
@@ -724,6 +725,8 @@ fi
%{_sbindir}/generate_support_bundle.pyo
%{_sbindir}/frr-reload.pyc
%{_sbindir}/frr-reload.pyo
+%{_sbindir}/frr_babeltrace.pyc
+%{_sbindir}/frr_babeltrace.pyo
%endif
diff --git a/tests/topotests/ospf6_topo2/r1/ospf6d.conf b/tests/topotests/ospf6_topo2/r1/ospf6d.conf
index 2e465e6d1f..1bf6550d9f 100644
--- a/tests/topotests/ospf6_topo2/r1/ospf6d.conf
+++ b/tests/topotests/ospf6_topo2/r1/ospf6d.conf
@@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
+debug ospf6 lsa nssa
+debug ospf6 lsa nssa originate
+debug ospf6 lsa nssa examine
+debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
-debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@@ -24,11 +27,11 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r1-eth0
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.254.254.1
area 0.0.0.1 stub
- interface r1-eth0 area 0.0.0.1
!
diff --git a/tests/topotests/ospf6_topo2/r2/ospf6d.conf b/tests/topotests/ospf6_topo2/r2/ospf6d.conf
index 4a1d10693d..7567c9cd64 100644
--- a/tests/topotests/ospf6_topo2/r2/ospf6d.conf
+++ b/tests/topotests/ospf6_topo2/r2/ospf6d.conf
@@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
+debug ospf6 lsa nssa
+debug ospf6 lsa nssa originate
+debug ospf6 lsa nssa examine
+debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
-debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@@ -24,14 +27,17 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r2-eth0
+ ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r2-eth1
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r2-eth2
+ ipv6 ospf6 area 0.0.0.2
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
@@ -42,7 +48,4 @@ router ospf6
default-information originate always metric 123
area 0.0.0.1 stub
area 0.0.0.2 nssa
- interface r2-eth0 area 0.0.0.1
- interface r2-eth1 area 0.0.0.0
- interface r2-eth2 area 0.0.0.2
!
diff --git a/tests/topotests/ospf6_topo2/r3/ospf6d.conf b/tests/topotests/ospf6_topo2/r3/ospf6d.conf
index 5faeb70e56..0fb4e7e365 100644
--- a/tests/topotests/ospf6_topo2/r3/ospf6d.conf
+++ b/tests/topotests/ospf6_topo2/r3/ospf6d.conf
@@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
+debug ospf6 lsa nssa
+debug ospf6 lsa nssa originate
+debug ospf6 lsa nssa examine
+debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
-debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@@ -24,6 +27,7 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r3-eth0
+ ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
@@ -31,5 +35,4 @@ router ospf6
ospf6 router-id 10.254.254.3
redistribute connected
redistribute static
- interface r3-eth0 area 0.0.0.0
!
diff --git a/tests/topotests/ospf6_topo2/r4/ospf6d.conf b/tests/topotests/ospf6_topo2/r4/ospf6d.conf
index 04d763f6a8..91f8df440c 100644
--- a/tests/topotests/ospf6_topo2/r4/ospf6d.conf
+++ b/tests/topotests/ospf6_topo2/r4/ospf6d.conf
@@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
+debug ospf6 lsa nssa
+debug ospf6 lsa nssa originate
+debug ospf6 lsa nssa examine
+debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
-debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@@ -24,11 +27,11 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r4-eth0
+ ipv6 ospf6 area 0.0.0.2
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.254.254.4
area 0.0.0.2 nssa
- interface r4-eth0 area 0.0.0.2
!
diff --git a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py
index 303bcd014d..eb8561c404 100644
--- a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py
+++ b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py
@@ -131,6 +131,8 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r4"])
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet")
def setup_module(mod):
"Sets up the pytest environment"
@@ -484,7 +486,7 @@ def test_area_filters():
pytest.skip(tgen.errors)
#
- # Configure import/export filters on r2 (ABR for area 1).
+ # Configure import/export filters on r2 (ABR for area 2).
#
config = """
configure terminal
@@ -544,6 +546,102 @@ def test_area_filters():
expect_ospfv3_routes("r1", routes, wait=30, type="inter-area")
+def test_nssa_range():
+ """
+ Test NSSA ABR ranges.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Configure new addresses on r4 and enable redistribution of connected
+ # routes.
+ config = """
+ configure terminal
+ interface r4-stubnet
+ ipv6 address 2001:db8:1000::1/128
+ ipv6 address 2001:db8:1000::2/128
+ router ospf6
+ redistribute connected
+ """
+ tgen.gears["r4"].vtysh_cmd(config)
+ logger.info("Expecting NSSA-translated external routes to be added on r3")
+ routes = {"2001:db8:1000::1/128": {}, "2001:db8:1000::2/128": {}}
+ expect_ospfv3_routes("r3", routes, wait=30, type="external-2")
+
+ # Configure an NSSA range on r2 (ABR for area 2).
+ config = """
+ configure terminal
+ router ospf6
+ area 2 nssa range 2001:db8:1000::/64
+ """
+ tgen.gears["r2"].vtysh_cmd(config)
+ logger.info("Expecting summarized routes to be removed from r3")
+ for route in ["2001:db8:1000::1/128", "2001:db8:1000::2/128"]:
+ test_func = partial(dont_expect_route, "r3", route, type="external-2")
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}'s {} summarized route still exists".format("r3", route)
+ assert result is None, assertmsg
+ logger.info("Expecting NSSA range to be added on r3")
+ routes = {
+ "2001:db8:1000::/64": {
+ "metricType":2,
+ "metricCost":20,
+ "metricCostE2":10,
+ }}
+ expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
+
+ # Change the NSSA range cost.
+ config = """
+ configure terminal
+ router ospf6
+ area 2 nssa range 2001:db8:1000::/64 cost 1000
+ """
+ tgen.gears["r2"].vtysh_cmd(config)
+ logger.info("Expecting NSSA range to be updated with new cost")
+ routes = {
+ "2001:db8:1000::/64": {
+ "metricType":2,
+ "metricCost":20,
+ "metricCostE2":1000,
+ }}
+ expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
+
+ # Configure the NSSA range to not be advertised.
+ config = """
+ configure terminal
+ router ospf6
+ area 2 nssa range 2001:db8:1000::/64 not-advertise
+ """
+ tgen.gears["r2"].vtysh_cmd(config)
+ logger.info("Expecting NSSA summary route to be removed")
+ route = "2001:db8:1000::/64"
+ test_func = partial(dont_expect_route, "r3", route, type="external-2")
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}'s {} NSSA summary route still exists".format("r3", route)
+ assert result is None, assertmsg
+
+ # Remove the NSSA range.
+ config = """
+ configure terminal
+ router ospf6
+ no area 2 nssa range 2001:db8:1000::/64
+ """
+ tgen.gears["r2"].vtysh_cmd(config)
+ logger.info("Expecting previously summarized routes to be re-added")
+ routes = {
+ "2001:db8:1000::1/128": {
+ "metricType":2,
+ "metricCost":20,
+ },
+ "2001:db8:1000::2/128": {
+ "metricType":2,
+ "metricCost":20,
+ },
+ }
+ expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
+
+
def teardown_module(_mod):
"Teardown the pytest environment"
tgen = get_topogen()
diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py
index 3058395758..27d830a119 100755
--- a/tools/frr_babeltrace.py
+++ b/tools/frr_babeltrace.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-'''
+"""
Usage: frr_babeltrace.py trace_path
FRR pushes data into lttng tracepoints in the least overhead way possible
@@ -23,7 +23,7 @@ more details.
You should have received a copy of the GNU General Public License along
with this program; see the file COPYING; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-'''
+"""
import ipaddress
import socket
@@ -33,56 +33,56 @@ import babeltrace
########################### common parsers - start ############################
def print_ip_addr(field_val):
- '''
+ """
pretty print "struct ipaddr"
- '''
+ """
if field_val[0] == socket.AF_INET:
addr = [str(fv) for fv in field_val[4:8]]
- return str(ipaddress.IPv4Address('.'.join(addr)))
+ return str(ipaddress.IPv4Address(".".join(addr)))
if field_val[0] == socket.AF_INET6:
- tmp = ''.join('%02x' % fb for fb in field_val[4:])
+ tmp = "".join("%02x" % fb for fb in field_val[4:])
addr = []
while tmp:
addr.append(tmp[:4])
tmp = tmp[4:]
- addr = ':'.join(addr)
+ addr = ":".join(addr)
return str(ipaddress.IPv6Address(addr))
if not field_val[0]:
- return ''
+ return ""
return field_val
def print_mac(field_val):
- '''
+ """
pretty print "u8 mac[6]"
- '''
- return ':'.join('%02x' % fb for fb in field_val)
+ """
+ return ":".join("%02x" % fb for fb in field_val)
def print_net_ipv4_addr(field_val):
- '''
+ """
pretty print ctf_integer_network ipv4
- '''
+ """
return str(ipaddress.IPv4Address(field_val))
def print_esi(field_val):
- '''
+ """
pretty print ethernet segment id, esi_t
- '''
- return ':'.join('%02x' % fb for fb in field_val)
+ """
+ return ":".join("%02x" % fb for fb in field_val)
def get_field_list(event):
- '''
+ """
only fetch fields added via the TP, skip metadata etc.
- '''
+ """
return event.field_list_with_scope(babeltrace.CTFScope.EVENT_FIELDS)
def parse_event(event, field_parsers):
- '''
+ """
Wild card event parser; doesn't make things any prettier
- '''
+ """
field_list = get_field_list(event)
field_info = {}
for field in field_list:
@@ -96,7 +96,7 @@ def parse_event(event, field_parsers):
############################ evpn parsers - start #############################
def parse_frr_bgp_evpn_mac_ip_zsend(event):
- '''
+ """
bgp evpn mac-ip parser; raw format -
ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac,
sizeof(struct ethaddr))
@@ -104,53 +104,156 @@ def parse_frr_bgp_evpn_mac_ip_zsend(event):
sizeof(struct ipaddr))
ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
ctf_array(unsigned char, esi, esi, sizeof(esi_t))
- '''
- field_parsers = {'ip': print_ip_addr,
- 'mac': print_mac,
- 'esi': print_esi,
- 'vtep': print_net_ipv4_addr}
+ """
+ field_parsers = {"ip": print_ip_addr,
+ "mac": print_mac,
+ "esi": print_esi,
+ "vtep": print_net_ipv4_addr}
parse_event(event, field_parsers)
def parse_frr_bgp_evpn_bum_vtep_zsend(event):
- '''
+ """
bgp evpn bum-vtep parser; raw format -
ctf_integer_network_hex(unsigned int, vtep,
pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr)
- '''
- field_parsers = {'vtep': print_net_ipv4_addr}
+ """
+ field_parsers = {"vtep": print_net_ipv4_addr}
parse_event(event, field_parsers)
def parse_frr_bgp_evpn_mh_nh_rmac_send(event):
- '''
+ """
bgp evpn nh-rmac parser; raw format -
ctf_array(unsigned char, rmac, &nh->rmac, sizeof(struct ethaddr))
- '''
- field_parsers = {'rmac': print_mac}
+ """
+ field_parsers = {"rmac": print_mac}
parse_event(event, field_parsers)
-############################ evpn parsers - end #############################
+def parse_frr_bgp_evpn_mh_local_es_add_zrecv(event):
+ """
+ bgp evpn local-es parser; raw format -
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ """
+ field_parsers = {"esi": print_esi,
+ "vtep": print_net_ipv4_addr}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_mh_local_es_del_zrecv(event):
+ """
+ bgp evpn local-es parser; raw format -
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ """
+ field_parsers = {"esi": print_esi}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv(event):
+ """
+ bgp evpn local-es-evi parser; raw format -
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ """
+ field_parsers = {"esi": print_esi}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv(event):
+ """
+ bgp evpn local-es-evi parser; raw format -
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ """
+ field_parsers = {"esi": print_esi}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_local_vni_add_zrecv(event):
+ """
+ bgp evpn local-vni parser; raw format -
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_integer_network_hex(unsigned int, mc_grp, mc_grp.s_addr)
+ """
+ field_parsers = {"vtep": print_net_ipv4_addr,
+ "mc_grp": print_net_ipv4_addr}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_local_l3vni_add_zrecv(event):
+ """
+ bgp evpn local-l3vni parser; raw format -
+ ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr)
+ ctf_array(unsigned char, svi_rmac, svi_rmac, sizeof(struct ethaddr))
+ ctf_array(unsigned char, vrr_rmac, vrr_rmac, sizeof(struct ethaddr))
+ """
+ field_parsers = {"vtep": print_net_ipv4_addr,
+ "svi_rmac": print_mac,
+ "vrr_rmac": print_mac}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_local_macip_add_zrecv(event):
+ """
+ bgp evpn local-mac-ip parser; raw format -
+ ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr))
+ ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr))
+ ctf_array(unsigned char, esi, esi, sizeof(esi_t))
+ """
+ field_parsers = {"ip": print_ip_addr,
+ "mac": print_mac,
+ "esi": print_esi}
+
+ parse_event(event, field_parsers)
+
+def parse_frr_bgp_evpn_local_macip_del_zrecv(event):
+ """
+ bgp evpn local-mac-ip del parser; raw format -
+ ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr))
+ ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr))
+ """
+ field_parsers = {"ip": print_ip_addr,
+ "mac": print_mac}
+
+ parse_event(event, field_parsers)
+
+############################ evpn parsers - end *#############################
def main():
- '''
+ """
FRR lttng trace output parser; babel trace plugin
- '''
- event_parsers = {'frr_bgp:evpn_mac_ip_zsend':
+ """
+ event_parsers = {"frr_bgp:evpn_mac_ip_zsend":
parse_frr_bgp_evpn_mac_ip_zsend,
- 'frr_bgp:evpn_bum_vtep_zsend':
+ "frr_bgp:evpn_bum_vtep_zsend":
parse_frr_bgp_evpn_bum_vtep_zsend,
- 'frr_bgp:evpn_mh_nh_rmac_zsend':
- parse_frr_bgp_evpn_mh_nh_rmac_send}
+ "frr_bgp:evpn_mh_nh_rmac_zsend":
+ parse_frr_bgp_evpn_mh_nh_rmac_send,
+ "frr_bgp:evpn_mh_local_es_add_zrecv":
+ parse_frr_bgp_evpn_mh_local_es_add_zrecv,
+ "frr_bgp:evpn_mh_local_es_del_zrecv":
+ parse_frr_bgp_evpn_mh_local_es_del_zrecv,
+ "frr_bgp:evpn_mh_local_es_evi_add_zrecv":
+ parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv,
+ "frr_bgp:evpn_mh_local_es_evi_del_zrecv":
+ parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv,
+ "frr_bgp:evpn_local_vni_add_zrecv":
+ parse_frr_bgp_evpn_local_vni_add_zrecv,
+ "frr_bgp:evpn_local_l3vni_add_zrecv":
+ parse_frr_bgp_evpn_local_l3vni_add_zrecv,
+ "frr_bgp:evpn_local_macip_add_zrecv":
+ parse_frr_bgp_evpn_local_macip_add_zrecv,
+ "frr_bgp:evpn_local_macip_del_zrecv":
+ parse_frr_bgp_evpn_local_macip_del_zrecv,
+}
# get the trace path from the first command line argument
trace_path = sys.argv[1]
# grab events
trace_collection = babeltrace.TraceCollection()
- trace_collection.add_traces_recursive(trace_path, 'ctf')
+ trace_collection.add_traces_recursive(trace_path, "ctf")
for event in trace_collection.events:
if event.name in event_parsers:
@@ -159,5 +262,5 @@ def main():
else:
parse_event(event, {})
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/tools/subdir.am b/tools/subdir.am
index e4b9ecd84f..64ca0bd514 100644
--- a/tools/subdir.am
+++ b/tools/subdir.am
@@ -21,6 +21,7 @@ sbin_SCRIPTS += \
tools/frrcommon.sh \
tools/frrinit.sh \
tools/generate_support_bundle.py \
+ tools/frr_babeltrace.py \
tools/watchfrr.sh \
# end
@@ -58,6 +59,7 @@ EXTRA_DIST += \
tools/frr.service \
tools/frr@.service \
tools/generate_support_bundle.py \
+ tools/frr_babeltrace.py \
tools/multiple-bgpd.sh \
tools/rrcheck.pl \
tools/rrlookup.pl \
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index 14d8ac442e..c3faf22d17 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -109,7 +109,8 @@ static int interface_list_ioctl(void)
unsigned int size;
ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n);
- ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT);
+ ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT,
+ VRF_DEFAULT_NAME);
if_add_update(ifp);
size = ifreq->ifr_addr.sa_len;
if (size < sizeof(ifreq->ifr_addr))
@@ -119,7 +120,8 @@ static int interface_list_ioctl(void)
}
#else
for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) {
- ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT);
+ ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT,
+ VRF_DEFAULT_NAME);
if_add_update(ifp);
ifreq++;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index fa3aabb195..187cd10e9c 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -972,17 +972,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
link_nsid = ns_id_get_absolute(ns_id, link_nsid);
}
- /* Add interface.
- * We add by index first because in some cases such as the master
- * interface, we have the index before we have the name. Fixing
- * back references on the slave interfaces is painful if not done
- * this way, i.e. by creating by ifindex.
- */
- ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id);
+ ifp = if_get_by_name(name, vrf_id, NULL);
set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */
- if_set_name(ifp, name);
-
ifp->flags = ifi->ifi_flags & 0x0000fffff;
ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
@@ -1814,7 +1806,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (ifp == NULL) {
/* unknown interface */
- ifp = if_get_by_name(name, vrf_id);
+ ifp = if_get_by_name(name, vrf_id, NULL);
} else {
/* pre-configured interface, learnt now */
if (ifp->vrf_id != vrf_id)
diff --git a/zebra/interface.c b/zebra/interface.c
index a68d00d55c..595862a6c9 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1616,7 +1616,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
struct listnode *node;
struct route_node *rn;
struct zebra_if *zebra_if;
- struct vrf *vrf;
char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
zebra_if = ifp->info;
@@ -1644,8 +1643,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
zebra_ptm_show_status(vty, NULL, ifp);
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- vty_out(vty, " vrf: %s\n", vrf->name);
+ vty_out(vty, " vrf: %s\n", ifp->vrf->name);
if (ifp->desc)
vty_out(vty, " Description: %s\n", ifp->desc);
@@ -1941,7 +1939,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
struct listnode *node;
struct route_node *rn;
struct zebra_if *zebra_if;
- struct vrf *vrf;
char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
char buf[BUFSIZ];
json_object *json_if;
@@ -1979,8 +1976,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
zebra_ptm_show_status(vty, json, ifp);
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- json_object_string_add(json_if, "vrfName", vrf->name);
+ json_object_string_add(json_if, "vrfName", ifp->vrf->name);
if (ifp->desc)
json_object_string_add(json_if, "description", ifp->desc);
@@ -4206,21 +4202,19 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
static int if_config_write(struct vty *vty)
{
- struct vrf *vrf0;
+ struct vrf *vrf;
struct interface *ifp;
zebra_ptm_write(vty);
- RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
- FOR_ALL_INTERFACES (vrf0, ifp) {
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ FOR_ALL_INTERFACES (vrf, ifp) {
struct zebra_if *if_data;
struct listnode *addrnode;
struct connected *ifc;
struct prefix *p;
- struct vrf *vrf;
if_data = ifp->info;
- vrf = vrf_lookup_by_id(ifp->vrf_id);
if (ifp->vrf_id == VRF_DEFAULT)
vty_frame(vty, "interface %s\n", ifp->name);
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index d9c69ceb6d..2db3e6e904 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -443,7 +443,8 @@ static int ifan_read(struct if_announcemsghdr *ifan)
__func__, ifan->ifan_index, ifan->ifan_name);
/* Create Interface */
- ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT);
+ ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT,
+ VRF_DEFAULT_NAME);
if_set_index(ifp, ifan->ifan_index);
if_get_metric(ifp);
@@ -624,7 +625,8 @@ int ifm_read(struct if_msghdr *ifm)
if (ifp == NULL) {
/* Interface that zebra was not previously aware of, so
* create. */
- ifp = if_create_name(ifname, VRF_DEFAULT);
+ ifp = if_get_by_name(ifname, VRF_DEFAULT,
+ VRF_DEFAULT_NAME);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: creating ifp for ifindex %d",
__func__, ifm->ifm_index);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 06528d3dbe..5b79de9697 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -776,6 +776,13 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
break;
}
+ /* This nexthop is a resolver for the parent nexthop.
+ * Set resolver flag for better clarity and delimiter
+ * in flat list of nexthops in json.
+ */
+ if (nexthop->rparent)
+ json_object_boolean_true_add(json_nexthop, "resolver");
+
if (nexthop->vrf_id != re->vrf_id)
json_object_string_add(json_nexthop, "vrf",
vrf_id_to_name(nexthop->vrf_id));