summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c141
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--bgpd/bgp_fsm.c8
-rw-r--r--doc/user/pim.rst11
-rw-r--r--isisd/isis_nb_config.c8
-rw-r--r--lib/if.c2
6 files changed, 103 insertions, 70 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ab80aff81b..331c0ece2d 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -421,14 +421,15 @@ static struct transit *transit_intern(struct transit *transit)
return find;
}
-void transit_unintern(struct transit *transit)
+static void transit_unintern(struct transit **transit)
{
- if (transit->refcnt)
- transit->refcnt--;
+ if ((*transit)->refcnt)
+ (*transit)->refcnt--;
- if (transit->refcnt == 0) {
- hash_release(transit_hash, transit);
- transit_free(transit);
+ if ((*transit)->refcnt == 0) {
+ hash_release(transit_hash, *transit);
+ transit_free(*transit);
+ *transit = NULL;
}
}
@@ -851,7 +852,7 @@ void bgp_attr_unintern_sub(struct attr *attr)
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
if (attr->transit)
- transit_unintern(attr->transit);
+ transit_unintern(&attr->transit);
if (attr->encap_subtlvs)
encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
@@ -2483,7 +2484,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Fetch attribute flag and type. */
@@ -2506,7 +2508,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Check extended attribue length bit. */
@@ -2527,7 +2530,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/* Set type to bitmap to check duplicate attribute. `type' is
@@ -2584,7 +2588,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
ndl + lfl + 1);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
struct bgp_attr_parser_args attr_args = {
@@ -2609,7 +2614,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
attr_args.total);
if (ret == BGP_ATTR_PARSE_PROCEED)
continue;
- return ret;
+ goto done;
}
/* OK check attribute and store it's value. */
@@ -2687,32 +2692,25 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
if (ret == BGP_ATTR_PARSE_EOR) {
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
- /* If hard error occurred immediately return to the caller. */
if (ret == BGP_ATTR_PARSE_ERROR) {
flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
"%s: Attribute %s, parse error", peer->host,
lookup_msg(attr_str, type, NULL));
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
if (ret == BGP_ATTR_PARSE_WITHDRAW) {
-
flog_warn(
EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
"%s: Attribute %s, parse error - treating as withdrawal",
peer->host, lookup_msg(attr_str, type, NULL));
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
+ goto done;
}
/* Check the fetched length. */
@@ -2722,9 +2720,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
peer->host, lookup_msg(attr_str, type, NULL));
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
}
@@ -2735,9 +2732,9 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
lookup_msg(attr_str, type, NULL));
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
/*
@@ -2756,16 +2753,14 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
if (bgp_attr_nexthop_valid(peer, attr) < 0) {
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
}
/* Check all mandatory well-known attributes are present */
- if ((ret = bgp_attr_check(peer, attr)) < 0) {
- if (as4_path)
- aspath_unintern(&as4_path);
- return ret;
- }
+ if ((ret = bgp_attr_check(peer, attr)) < 0)
+ goto done;
/*
* At this place we can see whether we got AS4_PATH and/or
@@ -2788,28 +2783,10 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
&as4_aggregator_addr)) {
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
- if (as4_path)
- aspath_unintern(&as4_path);
- return BGP_ATTR_PARSE_ERROR;
+ ret = BGP_ATTR_PARSE_ERROR;
+ goto done;
}
- /* At this stage, we have done all fiddling with as4, and the
- * resulting info is in attr->aggregator resp. attr->aspath
- * so we can chuck as4_aggregator and as4_path alltogether in
- * order to save memory
- */
- if (as4_path) {
- aspath_unintern(&as4_path); /* unintern - it is in the hash */
- /* The flag that we got this is still there, but that does not
- * do any trouble
- */
- }
- /*
- * The "rest" of the code does nothing with as4_aggregator.
- * there is no memory attached specifically which is not part
- * of the attr.
- * so ignoring just means do nothing.
- */
/*
* Finally do the checks on the aspath we did not do yet
* because we waited for a potentially synthesized aspath.
@@ -2817,21 +2794,59 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
ret = bgp_attr_aspath_check(peer, attr);
if (ret != BGP_ATTR_PARSE_PROCEED)
- return ret;
+ goto done;
}
- /* Finally intern unknown attribute. */
+
+ ret = BGP_ATTR_PARSE_PROCEED;
+done:
+
+ /*
+ * At this stage, we have done all fiddling with as4, and the
+ * resulting info is in attr->aggregator resp. attr->aspath so
+ * we can chuck as4_aggregator and as4_path alltogether in order
+ * to save memory
+ */
+ if (as4_path) {
+ /*
+ * unintern - it is in the hash
+ * The flag that we got this is still there, but that
+ * does not do any trouble
+ */
+ aspath_unintern(&as4_path);
+ }
+
+ if (ret != BGP_ATTR_PARSE_ERROR) {
+ /* Finally intern unknown attribute. */
+ if (attr->transit)
+ attr->transit = transit_intern(attr->transit);
+ if (attr->encap_subtlvs)
+ attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
+ ENCAP_SUBTLV_TYPE);
+#if ENABLE_BGP_VNC
+ if (attr->vnc_subtlvs)
+ attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs,
+ VNC_SUBTLV_TYPE);
+#endif
+ } else {
+ if (attr->transit) {
+ transit_free(attr->transit);
+ attr->transit = NULL;
+ }
+
+ bgp_attr_flush_encap(attr);
+ };
+
+ /* Sanity checks */
if (attr->transit)
- attr->transit = transit_intern(attr->transit);
+ assert(attr->transit->refcnt > 0);
if (attr->encap_subtlvs)
- attr->encap_subtlvs =
- encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+ assert(attr->encap_subtlvs->refcnt > 0);
#if ENABLE_BGP_VNC
if (attr->vnc_subtlvs)
- attr->vnc_subtlvs =
- encap_intern(attr->vnc_subtlvs, VNC_SUBTLV_TYPE);
+ assert(attr->vnc_subtlvs->refcnt > 0);
#endif
- return BGP_ATTR_PARSE_PROCEED;
+ return ret;
}
/*
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 13ed3e1ee3..40e87e190a 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -304,9 +304,6 @@ extern unsigned long int attr_unknown_count(void);
extern int cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern(struct cluster_list *);
-/* Transit attribute prototypes. */
-void transit_unintern(struct transit *);
-
/* Below exported for unit-test purposes only */
struct bgp_attr_parser_args {
struct peer *peer;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 6460ff76fe..8b84d696dc 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -164,6 +164,14 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
bgp_writes_off(from_peer);
bgp_reads_off(from_peer);
+ /*
+ * Before exchanging FD remove doppelganger from
+ * keepalive peer hash. It could be possible conf peer
+ * fd is set to -1. If blocked on lock then keepalive
+ * thread can access peer pointer with fd -1.
+ */
+ bgp_keepalives_off(from_peer);
+
BGP_TIMER_OFF(peer->t_routeadv);
BGP_TIMER_OFF(peer->t_connect);
BGP_TIMER_OFF(peer->t_connect_check_r);
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 4f9c573a24..1e2b697d18 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -197,8 +197,8 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
Set the pim hello and hold interval for a interface.
-.. index:: ip pim sm
-.. clicmd:: ip pim sm
+.. index:: ip pim
+.. clicmd:: ip pim
Tell pim that we would like to use this interface to form pim neighbors
over. Please note that this command does not enable the reception of IGMP
@@ -252,6 +252,13 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
10 deciseconds. 'no' form of this command is used to to configure back to the
default value.
+.. index:: ip mroute INTERFACE A.B.C.D [A.B.C.D]
+.. clicmd:: ip mroute INTERFACE A.B.C.D [A.B.C.D]
+
+ Set a static multicast route for a traffic coming on the current interface to
+ be forwarded on the given interface if the traffic matches the group address
+ and optionally the source address.
+
.. _pim-multicast-rib-insertion:
PIM Multicast RIB insertion:
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 820cfaa426..d14704b4ee 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -1550,9 +1550,13 @@ int lib_interface_isis_destroy(enum nb_event event,
circuit = nb_running_unset_entry(dnode);
if (!circuit)
return NB_ERR_INCONSISTENCY;
- if (circuit->state == C_STATE_UP || circuit->state == C_STATE_CONF)
- isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area);
+ /* disable both AFs for this circuit. this will also update the
+ * CSM state by sending an ISIS_DISABLED signal. If there is no
+ * area associated to the circuit there is nothing to do
+ */
+ if (circuit->area)
+ isis_circuit_af_set(circuit, false, false);
return NB_OK;
}
diff --git a/lib/if.c b/lib/if.c
index 20215640e6..31c1d9e8ba 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -262,7 +262,9 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
"/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
ifp->name, old_vrf->name);
if (if_dnode) {
+ nb_running_unset_entry(if_dnode->parent);
yang_dnode_change_leaf(if_dnode, vrf->name);
+ nb_running_set_entry(if_dnode->parent, ifp);
running_config->version++;
}
}