ospf6d: fix ifmtu settings when kernel changes values

Problem reported by customer that if an mtu value was set in the kernel,
quagga/frr would get very confused about what had been configured and
what had been learned.  This caused peers to not be successfully established.
Resolved by keeping a configuration value separate than the operational value
and set the operational accordingly.  If configured, it wins unless the config
defines a value that is higher than the kernel supports.

Ticket: CM-16876
Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
Reviewed By: CCR-6399
Testing Done: Manual testing successful, submitter tested, ospf-smoke completed
with no new failures.
This commit is contained in:
Don Slice 2017-06-22 09:17:24 -07:00
parent 8ea37652c7
commit 0c7ef48afe
2 changed files with 30 additions and 7 deletions

View File

@ -202,6 +202,7 @@ ospf6_interface_create (struct interface *ifp)
oi->state = OSPF6_INTERFACE_DOWN; oi->state = OSPF6_INTERFACE_DOWN;
oi->flag = 0; oi->flag = 0;
oi->mtu_ignore = 0; oi->mtu_ignore = 0;
oi->c_ifmtu = 0;
/* Try to adjust I/O buffer size with IfMtu */ /* Try to adjust I/O buffer size with IfMtu */
oi->ifmtu = ifp->mtu6; oi->ifmtu = ifp->mtu6;
@ -388,6 +389,22 @@ ospf6_interface_state_update (struct interface *ifp)
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
return; return;
/* Adjust the mtu values if the kernel told us something new */
if (ifp->mtu6 != oi->ifmtu)
{
/* If nothing configured, just accept it */
if (!oi->c_ifmtu)
oi->ifmtu = ifp->mtu6;
else if (oi->c_ifmtu > ifp->mtu6)
{
oi->ifmtu = ifp->mtu6;
zlog_warn ("Configured mtu %u on %s overridden by kernel %u",
oi->c_ifmtu, ifp->name, ifp->mtu6);
}
else
oi->ifmtu = oi->c_ifmtu;
}
if (if_is_operative (ifp) if (if_is_operative (ifp)
&& (ospf6_interface_get_linklocal_address(oi->interface) && (ospf6_interface_get_linklocal_address(oi->interface)
|| if_is_loopback(oi->interface))) || if_is_loopback(oi->interface)))
@ -1112,7 +1129,7 @@ DEFUN (ipv6_ospf6_ifmtu,
ifmtu = strtol (argv[idx_number]->arg, NULL, 10); ifmtu = strtol (argv[idx_number]->arg, NULL, 10);
if (oi->ifmtu == ifmtu) if (oi->c_ifmtu == ifmtu)
return CMD_SUCCESS; return CMD_SUCCESS;
if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu)
@ -1129,13 +1146,13 @@ DEFUN (ipv6_ospf6_ifmtu,
{ {
vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).%s", vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).%s",
ifp->name, iobuflen, VNL); ifp->name, iobuflen, VNL);
oi->ifmtu = iobuflen; oi->ifmtu = oi->c_ifmtu = iobuflen;
} }
else else
oi->ifmtu = ifmtu; oi->ifmtu = oi->c_ifmtu = ifmtu;
} }
else else
oi->ifmtu = ifmtu; oi->ifmtu = oi->c_ifmtu = ifmtu;
/* re-establish adjacencies */ /* re-establish adjacencies */
for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
@ -1149,11 +1166,12 @@ DEFUN (ipv6_ospf6_ifmtu,
DEFUN (no_ipv6_ospf6_ifmtu, DEFUN (no_ipv6_ospf6_ifmtu,
no_ipv6_ospf6_ifmtu_cmd, no_ipv6_ospf6_ifmtu_cmd,
"no ipv6 ospf6 ifmtu", "no ipv6 ospf6 ifmtu [(1-65535)]",
NO_STR NO_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Interface MTU\n" "Interface MTU\n"
"OSPFv3 Interface MTU\n"
) )
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
@ -1184,6 +1202,8 @@ DEFUN (no_ipv6_ospf6_ifmtu,
else else
oi->ifmtu = ifp->mtu; oi->ifmtu = ifp->mtu;
oi->c_ifmtu = 0;
/* re-establish adjacencies */ /* re-establish adjacencies */
for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
{ {
@ -1745,8 +1765,8 @@ config_write_ospf6_interface (struct vty *vty)
if (ifp->desc) if (ifp->desc)
vty_out (vty, " description %s%s", ifp->desc, VNL); vty_out (vty, " description %s%s", ifp->desc, VNL);
if (ifp->mtu6 != oi->ifmtu) if (oi->c_ifmtu)
vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->ifmtu, VNL); vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->c_ifmtu, VNL);
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
vty_out (vty, " ipv6 ospf6 cost %d%s", vty_out (vty, " ipv6 ospf6 cost %d%s",

View File

@ -76,6 +76,9 @@ struct ospf6_interface
/* I/F MTU */ /* I/F MTU */
u_int32_t ifmtu; u_int32_t ifmtu;
/* Configured MTU */
u_int32_t c_ifmtu;
/* Interface State */ /* Interface State */
u_char state; u_char state;