From dec8e5ff71f65d68649fac6fe73f1b28fded3470 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Oct 2015 06:30:28 +0100 Subject: [PATCH 1/6] get_parent_interface() - add support for vlans configured as a vlan but not an interface One scenario when this happens is a vlan used solely as a PPPoE port. --- src/etc/inc/interfaces.inc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index f7e60a6f17..180ce6ef3e 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -4539,6 +4539,20 @@ function get_parent_interface($interface, $avoidrecurse = false) { } } + if (empty($parents)) { + // Handle _vlans not assigned to an interface + if (strpos($realif, '_vlan') !== FALSE) { + if (is_array($config['vlans']['vlan'])) { + foreach ($config['vlans']['vlan'] as $vlanidx => $vlan) { + if ($realif == $vlan['vlanif']) { + $parents[0] = $vlan['if']; + break; + } + } + } + } + } + if (empty($parents)) { $parents[0] = $realif; } From 65176697862bec2cea7ba5dbb855bc27de3bd3a6 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Oct 2015 06:35:00 +0100 Subject: [PATCH 2/6] Add interface_mtu_wanted_for_pppoe() Returns the MTU wanted if an interface or vlan is used as a PPPoE port. --- src/etc/inc/interfaces.inc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 180ce6ef3e..3e9fd213a5 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -3077,6 +3077,44 @@ function interface_vlan_adapt_mtu($vlanifs, $mtu) { } } +function interface_mtu_wanted_for_pppoe($realif) { + global $config; + + $mtu = 0; + + if (is_array($config['ppps']) && is_array($config['ppps']['ppp'])) { + foreach ($config['ppps']['ppp'] as $ppp) { + if ($ppp['type'] == "pppoe") { + $ports = explode(',',$ppp['ports']); + $mtu_wanted = 1500; + foreach ($ports as $pid => $port) { + if (get_real_interface($port) == $realif) { + // use the MTU configured on the interface ... + if (is_array($config['interfaces'])) { + foreach ($config['interfaces'] as $interface) { + if ($interface['if'] != $ppp['if']) + continue; + if (!empty($interface['mtu'])) + $mtu_wanted = intval($interface['mtu']) + 8; + } + } + // ... unless there is an MTU configured on the port in question + if (!empty($ppp['mtu'])) { + $mtus = explode(',',$ppp['mtu']); + if (!empty($mtus[$pid])) + $mtu_wanted = intval($mtus[$pid]) + 8; + } + if ($mtu_wanted > $mtu) + $mtu = $mtu_wanted; + } + } + } + } + } + + return $mtu; +} + function interface_configure($interface = "wan", $reloadall = false, $linkupevent = false) { global $config, $g; global $interface_sn_arr_cache, $interface_ip_arr_cache; From 4cd0e27d1a6b2926880c9f3e8cabadd580ba2c39 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Oct 2015 06:51:30 +0100 Subject: [PATCH 3/6] Adjust interface MTUs for PPPoE but do not override explicitly configured MTUs --- src/etc/inc/interfaces.inc | 77 +++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 3e9fd213a5..218f42954e 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -3047,6 +3047,10 @@ function interface_vlan_mtu_configured($realhwif, $mtu) { $mtu = $config['interfaces'][$assignedport]['mtu']; } } + $pppoe_mtu = interface_mtu_wanted_for_pppoe($vlan['vlanif']); + if ($pppoe_mtu > $mtu) { + $mtu = $pppoe_mtu; + } } } @@ -3063,16 +3067,23 @@ function interface_vlan_adapt_mtu($vlanifs, $mtu) { /* All vlans need to use the same mtu value as their parent. */ foreach ($vlanifs as $vlan) { $assignedport = convert_real_interface_to_friendly_interface_name($vlan['vlanif']); + $pppoe_mtu = interface_mtu_wanted_for_pppoe($vlan['vlanif']); if (!empty($assignedport)) { if (!empty($config['interfaces'][$assignedport]['mtu'])) { pfSense_interface_mtu($vlan['vlanif'], $config['interfaces'][$assignedport]['mtu']); + } else if ($pppoe_mtu != 0) { + pfSense_interface_mtu($vlan['vlanif'], $pppoe_mtu); } else { if (get_interface_mtu($vlan['vlanif']) != $mtu) { pfSense_interface_mtu($vlan['vlanif'], $mtu); } } - } else if (get_interface_mtu($vlan['vlanif']) != $mtu) { - pfSense_interface_mtu($vlan['vlanif'], $mtu); + } else { + if ($pppoe_mtu != 0) { + pfSense_interface_mtu($vlan['vlanif'], $pppoe_mtu); + } else if (get_interface_mtu($vlan['vlanif']) != $mtu) { + pfSense_interface_mtu($vlan['vlanif'], $mtu); + } } } } @@ -3233,32 +3244,64 @@ function interface_configure($interface = "wan", $reloadall = false, $linkupeven interfaces_bring_up($wancfg['if']); } - if (!empty($wancfg['mtu'])) { - if (stristr($realif, "_vlan")) { - $assignedparent = convert_real_interface_to_friendly_interface_name($realhwif); + $mtuif = $realif; + $mtuhwif = $realhwif; + $wantedmtu = 0; + + /* adjust MTU of parent interface of PPPoE interface if this does not violate explicit configuration */ + if (interface_isppp_type($interface)) { + $mtuif = $realhwif; + $mtuhwif_array = get_parent_interface($mtuif); + $mtuhwif = $mtuhwif_array[0]; + $parent_mtu_configured = false; + if (is_array($config['interfaces'])) { + foreach ($config['interfaces'] as $tmpinterface) { + if ($tmpinterface['if'] == $mtuif && !empty($tmpinterface['mtu'])) { + $parent_mtu_configured = true; + break; + } + } + } + if (!$parent_mtu_configured) { + $wantedmtu = interface_mtu_wanted_for_pppoe($mtuif); + } + } + + if (is_array($config['interfaces'])) { + foreach ($config['interfaces'] as $tmpinterface) { + if ($tmpinterface['if'] == $mtuif && !empty($tmpinterface['mtu'])) { + $wantedmtu = $tmpinterface['mtu']; + break; + } + } + } + + if ($wantedmtu != 0) { + if (stristr($mtuif, "_vlan")) { + $assignedparent = convert_real_interface_to_friendly_interface_name($mtuhwif); if (!empty($assignedparent) && !empty($config['interfaces'][$assignedparent]['mtu'])) { $parentmtu = $config['interfaces'][$assignedparent]['mtu']; if ($wancfg['mtu'] > $parentmtu) { - log_error("There is a conflict on MTU between parent {$realhwif} and VLAN({$realif})"); + log_error("There is a conflict on MTU between parent {$mtuhwif} and VLAN({$mtuif})"); } } else { $parentmtu = 0; } - $parentmtu = interface_vlan_mtu_configured($realhwif, $parentmtu); + $parentmtu = interface_vlan_mtu_configured($mtuhwif, $parentmtu); - if (get_interface_mtu($realhwif) != $parentmtu) { - pfSense_interface_mtu($realhwif, $parentmtu); + if (get_interface_mtu($mtuhwif) != $parentmtu) { + pfSense_interface_mtu($mtuhwif, $parentmtu); } /* All vlans need to use the same mtu value as their parent. */ - interface_vlan_adapt_mtu(link_interface_to_vlans($realhwif), $parentmtu); - } else if (substr($realif, 0, 4) == 'lagg') { + interface_vlan_adapt_mtu(link_interface_to_vlans($mtuhwif), $parentmtu); + } else if (substr($mtuif, 0, 4) == 'lagg') { /* LAGG interface must be destroyed and re-created to change MTU */ - if ($wancfg['mtu'] != get_interface_mtu($realif)) { + if ($wantedmtu != get_interface_mtu($mtuif)) { if (isset($config['laggs']['lagg']) && is_array($config['laggs']['lagg'])) { foreach ($config['laggs']['lagg'] as $lagg) { - if ($lagg['laggif'] == $realif) { + if ($lagg['laggif'] == $mtuif) { interface_lagg_configure($lagg); break; } @@ -3266,14 +3309,14 @@ function interface_configure($interface = "wan", $reloadall = false, $linkupeven } } } else { - if ($wancfg['mtu'] != get_interface_mtu($realif)) { - pfSense_interface_mtu($realif, $wancfg['mtu']); + if ($wantedmtu != get_interface_mtu($mtuif)) { + pfSense_interface_mtu($mtuif, $wantedmtu); } /* This case is needed when the parent of vlans is being configured */ - $vlans = link_interface_to_vlans($realif); + $vlans = link_interface_to_vlans($mtuif); if (is_array($vlans)) { - interface_vlan_adapt_mtu($vlans, $wancfg['mtu']); + interface_vlan_adapt_mtu($vlans, $wantedmtu); } unset($vlans); } From 6a74d2d7e3e0cbd1e6c9de662dd0e0e02a209733 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Oct 2015 07:22:29 +0100 Subject: [PATCH 4/6] Add RFC4638 support (MTU > 1492) to the PPPoE client --- src/etc/inc/interfaces.inc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 218f42954e..f321d60684 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -1851,10 +1851,18 @@ EOD; if (empty($mtus[$pid])) { $mtus[$pid] = $defaultmtu; } - $mpdconf .= << (get_interface_mtu($port) - 8)) { + $mtus[$pid] = get_interface_mtu($port) - 8; + } + } + if (! ($type == "pppoe" && $mtus[$pid] > 1492) ) { + // N.B. MTU for PPPoE with MTU > 1492 is set using pppoe max-payload - see below + $mpdconf .= << 1492) { + $mpdconf .= << Date: Sat, 10 Oct 2015 22:59:59 +0100 Subject: [PATCH 5/6] Limit interface MTU to 1500 if no explicit MTU configured Without this change, setting the MTU of a PPPoE interface with a VLAN parent interface above 1492 will result in the MTU of other VLANs on the same physical NIC that are not explicitly configured to rise above 1500. It seems unwise - and a Principle of Least Astonishment breach - for an MTU requiring Ethernet jumbo frames to come about without explicit configuration. --- src/etc/inc/interfaces.inc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index f321d60684..d30866f75f 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -3088,15 +3088,15 @@ function interface_vlan_adapt_mtu($vlanifs, $mtu) { } else if ($pppoe_mtu != 0) { pfSense_interface_mtu($vlan['vlanif'], $pppoe_mtu); } else { - if (get_interface_mtu($vlan['vlanif']) != $mtu) { - pfSense_interface_mtu($vlan['vlanif'], $mtu); + if (get_interface_mtu($vlan['vlanif']) != (($mtu > 1500) ? 1500 : $mtu)) { + pfSense_interface_mtu($vlan['vlanif'], (($mtu > 1500) ? 1500 : $mtu)); } } } else { if ($pppoe_mtu != 0) { pfSense_interface_mtu($vlan['vlanif'], $pppoe_mtu); - } else if (get_interface_mtu($vlan['vlanif']) != $mtu) { - pfSense_interface_mtu($vlan['vlanif'], $mtu); + } else if (get_interface_mtu($vlan['vlanif']) != (($mtu > 1500) ? 1500 : $mtu)) { + pfSense_interface_mtu($vlan['vlanif'], (($mtu > 1500) ? 1500 : $mtu)); } } } @@ -3290,6 +3290,11 @@ function interface_configure($interface = "wan", $reloadall = false, $linkupeven } } + // Limit the MTU to 1500 if no explicit MTU configured + if ($wantedmtu == 0 && get_interface_mtu($mtuif) > 1500) { + $wantedmtu = 1500; + } + if ($wantedmtu != 0) { if (stristr($mtuif, "_vlan")) { $assignedparent = convert_real_interface_to_friendly_interface_name($mtuhwif); From 2e4cad90499f968474c4eca0852f352f1526b617 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 11 Oct 2015 03:53:16 +0100 Subject: [PATCH 6/6] Coding style fixes in interface_mtu_wanted_for_pppoe() --- src/etc/inc/interfaces.inc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index d30866f75f..8adadc024c 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -3117,20 +3117,24 @@ function interface_mtu_wanted_for_pppoe($realif) { // use the MTU configured on the interface ... if (is_array($config['interfaces'])) { foreach ($config['interfaces'] as $interface) { - if ($interface['if'] != $ppp['if']) + if ($interface['if'] != $ppp['if']) { continue; - if (!empty($interface['mtu'])) + } + if (!empty($interface['mtu'])) { $mtu_wanted = intval($interface['mtu']) + 8; + } } } // ... unless there is an MTU configured on the port in question if (!empty($ppp['mtu'])) { $mtus = explode(',',$ppp['mtu']); - if (!empty($mtus[$pid])) + if (!empty($mtus[$pid])) { $mtu_wanted = intval($mtus[$pid]) + 8; + } } - if ($mtu_wanted > $mtu) + if ($mtu_wanted > $mtu) { $mtu = $mtu_wanted; + } } } }