2020#include "dhcp-lease-internal.h"
2121#include "env-file.h"
2222#include "ethtool-util.h"
23+ #include "event-util.h"
2324#include "fd-util.h"
2425#include "fileio.h"
2526#include "format-util.h"
@@ -243,6 +244,7 @@ static Link *link_free(Link *link) {
243244 strv_free (link -> alternative_names );
244245 free (link -> kind );
245246 free (link -> ssid );
247+ free (link -> previous_ssid );
246248 free (link -> driver );
247249
248250 unlink_and_free (link -> lease_file );
@@ -258,6 +260,8 @@ static Link *link_free(Link *link) {
258260
259261 network_unref (link -> network );
260262
263+ sd_event_source_disable_unref (link -> carrier_lost_timer );
264+
261265 return mfree (link );
262266}
263267
@@ -1580,16 +1584,30 @@ int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, voi
15801584}
15811585
15821586static int link_carrier_gained (Link * link ) {
1587+ bool force_reconfigure ;
15831588 int r ;
15841589
15851590 assert (link );
15861591
1592+ r = event_source_disable (link -> carrier_lost_timer );
1593+ if (r < 0 )
1594+ log_link_warning_errno (link , r , "Failed to disable carrier lost timer, ignoring: %m" );
1595+
1596+ /* If the SSID is changed, then the connected wireless network could be changed. So, always
1597+ * reconfigure the link. Which means e.g. the DHCP client will be restarted, and the correct
1598+ * network information will be gained.
1599+ * For non-wireless interfaces, we have no way to detect the connected network change. So,
1600+ * setting force_reconfigure = false. Note, both ssid and previous_ssid should be NULL for
1601+ * non-wireless interfaces, and streq_ptr() returns true. */
1602+ force_reconfigure = !streq_ptr (link -> previous_ssid , link -> ssid );
1603+ link -> previous_ssid = mfree (link -> previous_ssid );
1604+
15871605 if (IN_SET (link -> state , LINK_STATE_CONFIGURING , LINK_STATE_CONFIGURED )) {
15881606 /* At this stage, both wlan and link information should be up-to-date. Hence,
15891607 * it is not necessary to call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or
15901608 * NL80211_CMD_GET_STATION commands, and simply call link_reconfigure_impl().
15911609 * Note, link_reconfigure_impl() returns 1 when the link is reconfigured. */
1592- r = link_reconfigure_impl (link , /* force = */ false );
1610+ r = link_reconfigure_impl (link , force_reconfigure );
15931611 if (r != 0 )
15941612 return r ;
15951613 }
@@ -1615,6 +1633,45 @@ static int link_carrier_gained(Link *link) {
16151633 return 0 ;
16161634}
16171635
1636+ static int link_carrier_lost_impl (Link * link ) {
1637+ int r , ret = 0 ;
1638+
1639+ assert (link );
1640+
1641+ link -> previous_ssid = mfree (link -> previous_ssid );
1642+
1643+ if (IN_SET (link -> state , LINK_STATE_FAILED , LINK_STATE_LINGER ))
1644+ return 0 ;
1645+
1646+ if (!link -> network )
1647+ return 0 ;
1648+
1649+ r = link_stop_engines (link , false);
1650+ if (r < 0 )
1651+ ret = r ;
1652+
1653+ r = link_drop_config (link );
1654+ if (r < 0 && ret >= 0 )
1655+ ret = r ;
1656+
1657+ return ret ;
1658+ }
1659+
1660+ static int link_carrier_lost_handler (sd_event_source * s , uint64_t usec , void * userdata ) {
1661+ Link * link = userdata ;
1662+ int r ;
1663+
1664+ assert (link );
1665+
1666+ r = link_carrier_lost_impl (link );
1667+ if (r < 0 ) {
1668+ log_link_warning_errno (link , r , "Failed to process carrier lost event: %m" );
1669+ link_enter_failed (link );
1670+ }
1671+
1672+ return 0 ;
1673+ }
1674+
16181675static int link_carrier_lost (Link * link ) {
16191676 int r ;
16201677
@@ -1631,16 +1688,22 @@ static int link_carrier_lost(Link *link) {
16311688 if (!link -> network )
16321689 return 0 ;
16331690
1634- if (link -> network -> ignore_carrier_loss )
1691+ if (link -> network -> ignore_carrier_loss_usec == USEC_INFINITY )
16351692 return 0 ;
16361693
1637- r = link_stop_engines (link , false);
1638- if (r < 0 ) {
1639- link_enter_failed (link );
1640- return r ;
1641- }
1642-
1643- return link_drop_config (link );
1694+ if (link -> network -> ignore_carrier_loss_usec == 0 )
1695+ return link_carrier_lost_impl (link );
1696+
1697+ return event_reset_time_relative (link -> manager -> event ,
1698+ & link -> carrier_lost_timer ,
1699+ clock_boottime_or_monotonic (),
1700+ link -> network -> ignore_carrier_loss_usec ,
1701+ 0 ,
1702+ link_carrier_lost_handler ,
1703+ link ,
1704+ 0 ,
1705+ "link-carrier-loss" ,
1706+ true);
16441707}
16451708
16461709static int link_admin_state_up (Link * link ) {
0 commit comments