it's recommended to set the hello delay and hello interval with the same values.
The default value is 10 seconds.
-.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn])
+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood]|point-to-point [dmvpn])
When configuring a point-to-point network on an interface and the interface
has a /32 address associated with then OSPF will treat the interface
point-to-point, but the HUB will be a point-to-multipoint. To make this
topology work, specify the optional 'dmvpn' parameter at the spoke.
+ When the network is configured as point-to-multipoint and `delay-reflood`
+ is specified, LSAs received on the interface from neighbors on the
+ interface will not be flooded back out on the interface immediately.
+ Rather, they will be added to the neighbor's link state retransmission
+ list and only sent to the neighbor if the neighbor doesn't acknowledge
+ the LSA prior to the link state retransmission timer expiring.
+
Set explicitly network type for specified interface.
.. clicmd:: ip ospf priority (0-255)
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
+#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
#define OSPF_AREA_RANGE_COST_UNSPEC -1U
OSPF_SEND_PACKET_DIRECT);
}
} else
- /* Optimization: for P2MP interfaces,
- don't send back out the incoming interface immediately,
- allow time to rx multicast ack to the rx'ed (multicast)
- update */
- if (retx_flag != 1 ||
- oi->type != OSPF_IFTYPE_POINTOMULTIPOINT || inbr == NULL ||
- oi != inbr->oi)
- ospf_ls_upd_send_lsa(oi->nbr_self, lsa,
- OSPF_SEND_PACKET_INDIRECT);
+ /* If P2MP delayed reflooding is configured and the LSA was
+ received from a neighbor on the P2MP interface, do not flood
+ if back out on the interface. The LSA will be retransmitted
+ upon expiration of each neighbor's retransmission timer. This
+ will allow time to receive a multicast multicast link state
+ acknoweldgement and remove the LSA from each neighbor's link
+ state retransmission list. */
+ if (oi->p2mp_delay_reflood &&
+ (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) &&
+ (inbr != NULL) && (oi == inbr->oi)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
+ zlog_debug(
+ "Delay reflooding for LSA[%s] from NBR %pI4 on interface %s",
+ dump_lsa_key(lsa),
+ inbr ? &(inbr->router_id)
+ : &(oi->ospf->router_id),
+ IF_NAME(oi));
+ } else
+ ospf_ls_upd_send_lsa(oi->nbr_self, lsa,
+ OSPF_SEND_PACKET_INDIRECT);
return 0;
}
oip->is_v_wait_set = false;
oip->ptp_dmvpn = 0;
+ oip->p2mp_delay_reflood = OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
return oip;
}
/* point-to-point DMVPN configuration */
uint8_t ptp_dmvpn;
+
+ /* point-to-multipoint delayed reflooding configuration */
+ bool p2mp_delay_reflood;
};
enum { MEMBER_ALLROUTERS = 0,
/* point-to-point DMVPN configuration */
uint8_t ptp_dmvpn;
+ /* point-to-multipoint delayed reflooding */
+ bool p2mp_delay_reflood;
+
/* State of Interface State Machine. */
uint8_t state;
/* OSPF Authentication information */
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
+ if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
+ if (use_json)
+ json_object_boolean_add(json_interface_sub,
+ "p2mpDelayReflood",
+ oi->p2mp_delay_reflood);
+ else
+ vty_out(vty,
+ " %sDelay reflooding LSAs received on P2MP interface\n",
+ oi->p2mp_delay_reflood ? "" : "Don't ");
+ }
}
}
}
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
- "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn]>",
+ "ip ospf network <broadcast|"
+ "non-broadcast|"
+ "point-to-multipoint [delay-reflood]|"
+ "point-to-point [dmvpn]>",
"IP Information\n"
"OSPF interface commands\n"
"Network type\n"
"Specify OSPF broadcast multi-access network\n"
"Specify OSPF NBMA network\n"
"Specify OSPF point-to-multipoint network\n"
+ "Specify OSPF delayed reflooding of LSAs received on P2MP interface\n"
"Specify OSPF point-to-point network\n"
"Specify OSPF point-to-point DMVPN network\n")
{
int idx = 0;
int old_type = IF_DEF_PARAMS(ifp)->type;
uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
+ uint8_t old_p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
struct route_node *rn;
if (old_type == OSPF_IFTYPE_LOOPBACK) {
}
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
+ OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
if (argv_find(argv, argc, "broadcast", &idx))
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
else if (argv_find(argv, argc, "non-broadcast", &idx))
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
- else if (argv_find(argv, argc, "point-to-multipoint", &idx))
+ else if (argv_find(argv, argc, "point-to-multipoint", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
- else if (argv_find(argv, argc, "point-to-point", &idx)) {
+ if (argv_find(argv, argc, "delay-reflood", &idx))
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true;
+ } else if (argv_find(argv, argc, "point-to-point", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
if (argv_find(argv, argc, "dmvpn", &idx))
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
}
- if (IF_DEF_PARAMS(ifp)->type == old_type
- && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn)
+ if (IF_DEF_PARAMS(ifp)->type == old_type &&
+ IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn &&
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood)
return CMD_SUCCESS;
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
continue;
oi->type = IF_DEF_PARAMS(ifp)->type;
+ oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
+ oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
- if (oi->state > ISM_Down) {
- OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
- OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
+ /*
+ * The OSPF interface only needs to be flapped if the network
+ * type or DMVPN parameter changes.
+ */
+ if (IF_DEF_PARAMS(ifp)->type != old_type ||
+ IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn) {
+ if (oi->state > ISM_Down) {
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
+ }
}
}
IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
+ OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
if (IF_DEF_PARAMS(ifp)->type == old_type)
return CMD_SUCCESS;
continue;
oi->type = IF_DEF_PARAMS(ifp)->type;
+ oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
+ oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
if (oi->state > ISM_Down) {
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
== OSPF_IFTYPE_POINTOPOINT
&& params->ptp_dmvpn)
vty_out(vty, " dmvpn");
+ if (params->type ==
+ OSPF_IFTYPE_POINTOMULTIPOINT &&
+ params->p2mp_delay_reflood)
+ vty_out(vty, " delay-reflood");
if (params != IF_DEF_PARAMS(ifp) && rn)
vty_out(vty, " %pI4",
&rn->p.u.prefix4);
skip network type setting. */
oi->type = IF_DEF_PARAMS(co->ifp)->type;
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
+ oi->p2mp_delay_reflood = IF_DEF_PARAMS(co->ifp)->p2mp_delay_reflood;
/* Add pseudo neighbor. */
ospf_nbr_self_reset(oi, oi->ospf->router_id);
write_test_footer(tc_name)
+def test_ospf_p2mp_tc_delay_reflood(request):
+ """OSPF IFSM -Verify "delay-reflood" parameter in p2mp network."""
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ r0 = tgen.gears["r0"]
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ global topo
+
+ step("Verify for interface with network type P2MP that delay-reflood is configured")
+ r0.vtysh_multicmd(
+ "conf t\ninterface r0-r1-eth0\nip ospf network point-to-multipoint delay-reflood"
+ )
+
+ dut = "r0"
+ input_dict = {
+ "r0": {
+ "links": {
+ "r1": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": True,
+ }
+ },
+ "r2": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ "r3": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ }
+ }
+ }
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ delay_reflood_cfg = (
+ tgen.net["r0"]
+ .cmd(
+ 'vtysh -c "show running" | grep "^ ip ospf network point-to-multipoint delay-reflood"'
+ )
+ .rstrip()
+ )
+
+ assertmsg = "delay-reflood' configuration applied, but not present in configuration"
+ assert (
+ delay_reflood_cfg == " ip ospf network point-to-multipoint delay-reflood"
+ ), assertmsg
+
+ step("Verify for interface with network type P2MP that delay-reflood is removed")
+ r0.vtysh_multicmd(
+ "conf t\ninterface r0-r1-eth0\nip ospf network point-to-multipoint"
+ )
+
+ input_dict = {
+ "r0": {
+ "links": {
+ "r1": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ "r2": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ "r3": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ }
+ }
+ }
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ delay_reflood_cfg = (
+ tgen.net["r0"]
+ .cmd(
+ 'vtysh -c "show running" | grep "^ ip ospf network point-to-multipoint delay-reflood"'
+ )
+ .rstrip()
+ )
+ assertmsg = (
+ "delay-reflood' configuration removed, but still present in configuration"
+ )
+ assert (
+ delay_reflood_cfg != " ip ospf network point-to-multipoint delay-reflood"
+ ), assertmsg
+
+ step(
+ "Verify for interface with network type P2MP that delay-reflood is removed with removal of network type"
+ )
+ r0.vtysh_multicmd(
+ "conf t\ninterface r0-r1-eth0\nip ospf network point-to-multipoint delay-reflood"
+ )
+ r0.vtysh_multicmd(
+ "conf t\ninterface r0-r1-eth0\nno ip ospf network point-to-multipoint"
+ )
+ r0.vtysh_multicmd(
+ "conf t\ninterface r0-r1-eth0\nip ospf network point-to-multipoint"
+ )
+
+ input_dict = {
+ "r0": {
+ "links": {
+ "r1": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ "r2": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ "r3": {
+ "ospf": {
+ "mcastMemberOspfAllRouters": True,
+ "ospfEnabled": True,
+ "networkType": "POINTOMULTIPOINT",
+ "p2mpDelayReflood": False,
+ }
+ },
+ }
+ }
+ }
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ delay_reflood_cfg = (
+ tgen.net["r0"]
+ .cmd(
+ 'vtysh -c "show running" | grep "^ ip ospf network point-to-multipoint delay-reflood"'
+ )
+ .rstrip()
+ )
+ assertmsg = (
+ "delay-reflood' configuration removed, but still present in configuration"
+ )
+ assert (
+ delay_reflood_cfg != " ip ospf network point-to-multipoint delay-reflood"
+ ), assertmsg
+
+ write_test_footer(tc_name)
+
+
@retry(retry_timeout=30)
def verify_ospf_json(tgen, dut, input_dict, cmd="show ip ospf database json"):
del tgen