Thank you. 
/Alin

-----Original Message-----
From: Tom Gundersen [mailto:t...@jklm.no] 
Sent: Friday, February 27, 2015 7:05 PM
To: Rauta, Alin
Cc: systemd-devel@lists.freedesktop.org; Kinsella, Ray
Subject: Re: [systemd-devel] [PATCH v4] Added support for Uplink Failure 
Detection using BindCarrier

Hi Alin,

On Fri, Feb 27, 2015 at 6:44 AM, Rauta, Alin <alin.ra...@intel.com> wrote:
> Can we please draw a conclusion in this case ?

Sorry for the long time it has taken to get this patchset reviewed.

I have just gone through it now, and it looks great. You are right that the 
LINK_STATE_DOWN can be done separately. Pushed.

Thanks for all your work on this. Much appreciated!

Cheers,

Tom

> -----Original Message-----
> From: systemd-devel 
> [mailto:systemd-devel-boun...@lists.freedesktop.org] On Behalf Of 
> Rauta, Alin
> Sent: Friday, February 20, 2015 10:37 AM
> To: Tom Gundersen
> Cc: Kinsella, Ray; systemd-devel@lists.freedesktop.org
> Subject: Re: [systemd-devel] [PATCH v4] Added support for Uplink 
> Failure Detection using BindCarrier
>
> Hi Tom,
> Thank you. Please let me know if you have any questions regarding the 
> implementation.
> We can have another patch for the DOWN logic. It's a little bit complicated 
> since we don't have UP either and since during UP operation we don't know the 
> previous port state so that we get back to it.
> Best Regards,
> Alin
>
> -----Original Message-----
> From: Tom Gundersen [mailto:t...@jklm.no]
> Sent: Friday, February 20, 2015 10:27 AM
> To: Rauta, Alin
> Cc: lenn...@poettering.net; zbys...@in.waw.pl; 
> systemd-devel@lists.freedesktop.org; Kinsella, Ray
> Subject: Re: [PATCH v4] Added support for Uplink Failure Detection 
> using BindCarrier
>
> On Fri, Feb 20, 2015 at 10:50 AM, Rauta, Alin <alin.ra...@intel.com> wrote:
>> Hi Tom, Lennart, Zbyszek,
>> Did you have any chance to look at this patch version ?
>
> I hope to review it this weekend. I might go ahead and implement the DOWN 
> logic independently if that is still an issue (saw your question, but didn't 
> yet look at how you dealt with it in the patch). We need that anyway for 
> manually UP/DOWN of networks.
>
>> -----Original Message-----
>> From: Rauta, Alin
>> Sent: Tuesday, February 17, 2015 12:07 PM
>> To: t...@jklm.no; lenn...@poettering.net; zbys...@in.waw.pl
>> Cc: systemd-devel@lists.freedesktop.org; Kinsella, Ray; Rauta, Alin
>> Subject: [PATCH v4] Added support for Uplink Failure Detection using 
>> BindCarrier
>>
>> ---
>>  man/systemd.network.xml                  |  11 +
>>  src/libsystemd/sd-network/sd-network.c   |   8 +
>>  src/network/networkctl.c                 |  43 ++--
>>  src/network/networkd-link.c              | 394 
>> +++++++++++++++++++++++++++++--
>>  src/network/networkd-link.h              |   3 +
>>  src/network/networkd-network-gperf.gperf |   1 +
>>  src/network/networkd-network.c           |   1 +
>>  src/network/networkd.h                   |   2 +-
>>  src/systemd/sd-network.h                 |   6 +
>>  9 files changed, 438 insertions(+), 31 deletions(-)
>>
>> diff --git a/man/systemd.network.xml b/man/systemd.network.xml index
>> 485876b..60252e5 100644
>> --- a/man/systemd.network.xml
>> +++ b/man/systemd.network.xml
>> @@ -280,6 +280,17 @@
>>            </listitem>
>>          </varlistentry>
>>          <varlistentry>
>> +          <term><varname>BindCarrier=</varname></term>
>> +          <listitem>
>> +            <para>A port or a list of ports. When set, controls the
>> +            behaviour of the current interface. When all ports in the list
>> +            are in an operational down state, the current interface is 
>> brought
>> +            down. When at least one port has carrier, the current interface
>> +            is brought up.
>> +            </para>
>> +          </listitem>
>> +        </varlistentry>
>> +        <varlistentry>
>>            <term><varname>Address=</varname></term>
>>            <listitem>
>>              <para>A static IPv4 or IPv6 address and its prefix 
>> length, diff --git a/src/libsystemd/sd-network/sd-network.c
>> b/src/libsystemd/sd-network/sd-network.c
>> index c4713fe..fb5152c 100644
>> --- a/src/libsystemd/sd-network/sd-network.c
>> +++ b/src/libsystemd/sd-network/sd-network.c
>> @@ -264,6 +264,14 @@ _public_ int sd_network_link_get_domains(int ifindex, 
>> char ***ret) {
>>          return network_get_link_strv("DOMAINS", ifindex, ret);  }
>>
>> +_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) 
>> {
>> +        return network_get_link_strv("CARRIER_BOUND_TO", ifindex, 
>> +ret); }
>> +
>> +_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) 
>> {
>> +        return network_get_link_strv("CARRIER_BOUND_BY", ifindex, 
>> +ret); }
>> +
>>  _public_ int sd_network_link_get_wildcard_domain(int ifindex) {
>>          int r;
>>          _cleanup_free_ char *p = NULL, *s = NULL; diff --git 
>> a/src/network/networkctl.c b/src/network/networkctl.c index
>> aa83f32..0637513 100644
>> --- a/src/network/networkctl.c
>> +++ b/src/network/networkctl.c
>> @@ -508,6 +508,8 @@ static int link_status_one(
>>          const char *driver = NULL, *path = NULL, *vendor = NULL, *model = 
>> NULL, *link = NULL;
>>          const char *on_color_operational, *off_color_operational,
>>                     *on_color_setup, *off_color_setup;
>> +        _cleanup_strv_free_ char **carrier_bound_to = NULL;
>> +        _cleanup_strv_free_ char **carrier_bound_by = NULL;
>>          struct ether_addr e;
>>          unsigned iftype;
>>          int r, ifindex;
>> @@ -606,12 +608,15 @@ static int link_status_one(
>>
>>          sd_network_link_get_network_file(ifindex, &network);
>>
>> +        sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to);
>> +        sd_network_link_get_carrier_bound_by(ifindex,
>> + &carrier_bound_by);
>> +
>>          printf("%s%s%s %i: %s\n", on_color_operational, 
>> draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, 
>> name);
>>
>> -        printf("   Link File: %s\n"
>> -               "Network File: %s\n"
>> -               "        Type: %s\n"
>> -               "       State: %s%s%s (%s%s%s)\n",
>> +        printf("       Link File: %s\n"
>> +               "    Network File: %s\n"
>> +               "            Type: %s\n"
>> +               "           State: %s%s%s (%s%s%s)\n",
>>                 strna(link),
>>                 strna(network),
>>                 strna(t),
>> @@ -619,13 +624,13 @@ static int link_status_one(
>>                 on_color_setup, strna(setup_state), off_color_setup);
>>
>>          if (path)
>> -                printf("        Path: %s\n", path);
>> +                printf("            Path: %s\n", path);
>>          if (driver)
>> -                printf("      Driver: %s\n", driver);
>> +                printf("          Driver: %s\n", driver);
>>          if (vendor)
>> -                printf("      Vendor: %s\n", vendor);
>> +                printf("          Vendor: %s\n", vendor);
>>          if (model)
>> -                printf("       Model: %s\n", model);
>> +                printf("           Model: %s\n", model);
>>
>>          if (have_mac) {
>>                  _cleanup_free_ char *description = NULL; @@ -634,23 +639,29 
>> @@ static int link_status_one(
>>                  ieee_oui(hwdb, &e, &description);
>>
>>                  if (description)
>> -                        printf("  HW Address: %s (%s)\n", 
>> ether_addr_to_string(&e, ea), description);
>> +                        printf("      HW Address: %s (%s)\n", 
>> ether_addr_to_string(&e, ea), description);
>>                  else
>> -                        printf("  HW Address: %s\n", 
>> ether_addr_to_string(&e, ea));
>> +                        printf("      HW Address: %s\n", 
>> ether_addr_to_string(&e, ea));
>>          }
>>
>>          if (mtu > 0)
>> -                printf("         MTU: %u\n", mtu);
>> +                printf("             MTU: %u\n", mtu);
>>
>> -        dump_addresses(rtnl, "     Address: ", ifindex);
>> -        dump_gateways(rtnl, hwdb, "     Gateway: ", ifindex);
>> +        dump_addresses(rtnl, "         Address: ", ifindex);
>> +        dump_gateways(rtnl, hwdb, "         Gateway: ", ifindex);
>>
>>          if (!strv_isempty(dns))
>> -                dump_list("         DNS: ", dns);
>> +                dump_list("             DNS: ", dns);
>>          if (!strv_isempty(domains))
>> -                dump_list("      Domain: ", domains);
>> +                dump_list("          Domain: ", domains);
>>          if (!strv_isempty(ntp))
>> -                dump_list("         NTP: ", ntp);
>> +                dump_list("             NTP: ", ntp);
>> +
>> +        if (!strv_isempty(carrier_bound_to))
>> +                dump_list("Carrier Bound To: ", carrier_bound_to);
>> +
>> +        if (!strv_isempty(carrier_bound_by))
>> +                dump_list("Carrier Bound By: ", carrier_bound_by);
>>
>>          return 0;
>>  }
>> diff --git a/src/network/networkd-link.c 
>> b/src/network/networkd-link.c index f716e82..d718037 100644
>> --- a/src/network/networkd-link.c
>> +++ b/src/network/networkd-link.c
>> @@ -275,6 +275,8 @@ static int link_new(Manager *manager, 
>> sd_rtnl_message *message, Link **ret) {
>>
>>  static void link_free(Link *link) {
>>          Address *address;
>> +        Iterator i;
>> +        Link *carrier;
>>
>>          if (!link)
>>                  return;
>> @@ -312,6 +314,14 @@ static void link_free(Link *link) {
>>
>>          udev_device_unref(link->udev_device);
>>
>> +        HASHMAP_FOREACH (carrier, link->bound_to_links, i)
>> +                hashmap_remove(link->bound_to_links, 
>> INT_TO_PTR(carrier->ifindex));
>> +        hashmap_free(link->bound_to_links);
>> +
>> +        HASHMAP_FOREACH (carrier, link->bound_by_links, i)
>> +                hashmap_remove(link->bound_by_links, 
>> INT_TO_PTR(carrier->ifindex));
>> +        hashmap_free(link->bound_by_links);
>> +
>>          free(link);
>>  }
>>
>> @@ -358,19 +368,6 @@ static void link_set_state(Link *link, LinkState state) 
>> {
>>          return;
>>  }
>>
>> -void link_drop(Link *link) {
>> -        if (!link || link->state == LINK_STATE_LINGER)
>> -                return;
>> -
>> -        link_set_state(link, LINK_STATE_LINGER);
>> -
>> -        log_link_debug(link, "link removed");
>> -
>> -        link_unref(link);
>> -
>> -        return;
>> -}
>> -
>>  static void link_enter_unmanaged(Link *link) {
>>          assert(link);
>>
>> @@ -1151,13 +1148,319 @@ static int link_up(Link *link) {
>>          return 0;
>>  }
>>
>> +static int link_down_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void 
>> *userdata) {
>> +        _cleanup_link_unref_ Link *link = userdata;
>> +        int r;
>> +
>> +        assert(link);
>> +
>> +        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
>> +                return 1;
>> +
>> +        r = sd_rtnl_message_get_errno(m);
>> +        if (r < 0)
>> +                log_link_warning_errno(link, -r, "%-*s: could not 
>> + bring down interface: %m", IFNAMSIZ, link->ifname);
>> +
>> +        return 1;
>> +}
>> +
>> +static int link_down(Link *link) {
>> +        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
>> +        int r;
>> +
>> +        assert(link);
>> +        assert(link->manager);
>> +        assert(link->manager->rtnl);
>> +
>> +        log_link_debug(link, "bringing link down");
>> +
>> +        r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
>> +                                     RTM_SETLINK, link->ifindex);
>> +        if (r < 0) {
>> +                log_link_error(link, "Could not allocate RTM_SETLINK 
>> message");
>> +                return r;
>> +        }
>> +
>> +        r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
>> +        if (r < 0) {
>> +                log_link_error(link, "Could not set link flags: %s",
>> +                               strerror(-r));
>> +                return r;
>> +        }
>> +
>> +        r = sd_rtnl_call_async(link->manager->rtnl, req, link_down_handler, 
>> link,
>> +                               0, NULL);
>> +        if (r < 0) {
>> +                log_link_error(link,
>> +                               "Could not send rtnetlink message: %s",
>> +                               strerror(-r));
>> +                return r;
>> +        }
>> +
>> +        link_ref(link);
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_handle_bound_to_list(Link *link) {
>> +        Link *l;
>> +        Iterator i;
>> +        int r;
>> +        bool required_up = false;
>> +        bool link_is_up = false;
>> +
>> +        assert(link);
>> +
>> +        if (hashmap_isempty(link->bound_to_links))
>> +                return 0;
>> +
>> +        if (link->flags & IFF_UP)
>> +                link_is_up = true;
>> +
>> +        HASHMAP_FOREACH (l, link->bound_to_links, i)
>> +                if (link_has_carrier(l)) {
>> +                        required_up = true;
>> +                        break;
>> +                }
>> +
>> +        if (!required_up && link_is_up) {
>> +                r = link_down(link);
>> +                if (r < 0)
>> +                        return r;
>> +        } else if (required_up && !link_is_up) {
>> +                r = link_up(link);
>> +                if (r < 0)
>> +                        return r;
>> +        }
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_handle_bound_by_list(Link *link) {
>> +        Iterator i;
>> +        Link *l;
>> +        int r;
>> +
>> +        assert(link);
>> +
>> +        if (hashmap_isempty(link->bound_by_links))
>> +                return 0;
>> +
>> +        HASHMAP_FOREACH (l, link->bound_by_links, i) {
>> +                r = link_handle_bound_to_list(l);
>> +                if (r < 0)
>> +                        return r;
>> +        }
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
>> +        int r;
>> +
>> +        assert(link);
>> +        assert(carrier);
>> +
>> +        if (link == carrier)
>> +                return 0;
>> +
>> +        if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
>> +                return 0;
>> +
>> +        r = hashmap_ensure_allocated(h, NULL);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_new_bound_by_list(Link *link) {
>> +        Manager *m;
>> +        Link *carrier;
>> +        Iterator i;
>> +        int r;
>> +        bool list_updated = false;
>> +
>> +        assert(link);
>> +        assert(link->manager);
>> +
>> +        m = link->manager;
>> +
>> +        HASHMAP_FOREACH (carrier, m->links, i) {
>> +                if (!carrier->network)
>> +                        continue;
>> +
>> +                if (strv_isempty(carrier->network->bind_carrier))
>> +                        continue;
>> +
>> +                if (strv_fnmatch(carrier->network->bind_carrier, 
>> link->ifname, 0)) {
>> +                        r = link_put_carrier(link, carrier, 
>> &link->bound_by_links);
>> +                        if (r < 0)
>> +                                return r;
>> +
>> +                        list_updated = true;
>> +                }
>> +        }
>> +
>> +        if (list_updated)
>> +                link_save(link);
>> +
>> +        HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
>> +                r = link_put_carrier(carrier, link, 
>> &carrier->bound_to_links);
>> +                if (r < 0)
>> +                        return r;
>> +
>> +                link_save(carrier);
>> +        }
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_new_bound_to_list(Link *link) {
>> +        Manager *m;
>> +        Link *carrier;
>> +        Iterator i;
>> +        int r;
>> +        bool list_updated = false;
>> +
>> +        assert(link);
>> +        assert(link->manager);
>> +
>> +        if (!link->network)
>> +                return 0;
>> +
>> +        if (strv_isempty(link->network->bind_carrier))
>> +                return 0;
>> +
>> +        m = link->manager;
>> +
>> +        HASHMAP_FOREACH (carrier, m->links, i) {
>> +                if (strv_fnmatch(link->network->bind_carrier, 
>> carrier->ifname, 0)) {
>> +                        r = link_put_carrier(link, carrier, 
>> &link->bound_to_links);
>> +                        if (r < 0)
>> +                                return r;
>> +
>> +                        list_updated = true;
>> +                }
>> +        }
>> +
>> +        if (list_updated)
>> +                link_save(link);
>> +
>> +        HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
>> +                r = link_put_carrier(carrier, link, 
>> &carrier->bound_by_links);
>> +                if (r < 0)
>> +                        return r;
>> +
>> +                link_save(carrier);
>> +        }
>> +
>> +        return 0;
>> +}
>> +
>> +static int link_new_carrier_maps(Link *link) {
>> +        int r;
>> +
>> +        r = link_new_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        r = link_handle_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        r = link_new_bound_to_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        r = link_handle_bound_to_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        return 0;
>> +}
>> +
>> +static void link_free_bound_to_list(Link *link) {
>> +        Link *bound_to;
>> +        Iterator i;
>> +
>> +        HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
>> +                hashmap_remove(link->bound_to_links,
>> + INT_TO_PTR(bound_to->ifindex));
>> +
>> +                if (hashmap_remove(bound_to->bound_by_links, 
>> INT_TO_PTR(link->ifindex)))
>> +                        link_save(bound_to);
>> +        }
>> +
>> +        return;
>> +}
>> +
>> +static void link_free_bound_by_list(Link *link) {
>> +        Link *bound_by;
>> +        Iterator i;
>> +
>> +        HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
>> +                hashmap_remove(link->bound_by_links,
>> + INT_TO_PTR(bound_by->ifindex));
>> +
>> +                if (hashmap_remove(bound_by->bound_to_links, 
>> INT_TO_PTR(link->ifindex))) {
>> +                        link_save(bound_by);
>> +                        link_handle_bound_to_list(bound_by);
>> +                }
>> +        }
>> +
>> +        return;
>> +}
>> +
>> +static void link_free_carrier_maps(Link *link) {
>> +        bool list_updated = false;
>> +
>> +        assert(link);
>> +
>> +        if (!hashmap_isempty(link->bound_to_links)) {
>> +                link_free_bound_to_list(link);
>> +                list_updated = true;
>> +        }
>> +
>> +        if (!hashmap_isempty(link->bound_by_links)) {
>> +                link_free_bound_by_list(link);
>> +                list_updated = true;
>> +        }
>> +
>> +        if (list_updated)
>> +                link_save(link);
>> +
>> +        return;
>> +}
>> +
>> +void link_drop(Link *link) {
>> +        if (!link || link->state == LINK_STATE_LINGER)
>> +                return;
>> +
>> +        link_set_state(link, LINK_STATE_LINGER);
>> +
>> +        link_free_carrier_maps(link);
>> +
>> +        log_link_debug(link, "link removed");
>> +
>> +        link_unref(link);
>> +
>> +        return;
>> +}
>> +
>>  static int link_joined(Link *link) {
>>          int r;
>>
>>          assert(link);
>>          assert(link->network);
>>
>> -        if (!(link->flags & IFF_UP)) {
>> +        if (!hashmap_isempty(link->bound_to_links)) {
>> +                r = link_handle_bound_to_list(link);
>> +                if (r < 0)
>> +                        return r;
>> +        } else if (!(link->flags & IFF_UP)) {
>>                  r = link_up(link);
>>                  if (r < 0) {
>>                          link_enter_failed(link); @@ -1432,6 +1735,14 
>> @@ static int link_initialized_and_synced(sd_rtnl *rtnl, 
>> sd_rtnl_message *m,
>>
>>          log_link_debug(link, "link state is up-to-date");
>>
>> +        r = link_new_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>> +        r = link_handle_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>>          r = network_get(link->manager, link->udev_device, link->ifname,
>>                          &link->mac, &network);
>>          if (r == -ENOENT) {
>> @@ -1455,6 +1766,10 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, 
>> sd_rtnl_message *m,
>>          if (r < 0)
>>                  return r;
>>
>> +        r = link_new_bound_to_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>>          r = link_configure(link);
>>          if (r < 0)
>>                  return r;
>> @@ -1732,6 +2047,10 @@ static int link_carrier_gained(Link *link) {
>>                  }
>>          }
>>
>> +        r = link_handle_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>>          return 0;
>>  }
>>
>> @@ -1746,6 +2065,10 @@ static int link_carrier_lost(Link *link) {
>>                  return r;
>>          }
>>
>> +        r = link_handle_bound_by_list(link);
>> +        if (r < 0)
>> +                return r;
>> +
>>          return 0;
>>  }
>>
>> @@ -1785,16 +2108,26 @@ int link_update(Link *link, sd_rtnl_message *m) {
>>                  link_ref(link);
>>                  log_link_info(link, "link readded");
>>                  link_set_state(link, LINK_STATE_ENSLAVING);
>> +
>> +                r = link_new_carrier_maps(link);
>> +                if (r < 0)
>> +                        return r;
>>          }
>>
>>          r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
>>          if (r >= 0 && !streq(ifname, link->ifname)) {
>>                  log_link_info(link, "renamed to %s", ifname);
>>
>> +                link_free_carrier_maps(link);
>> +
>>                  free(link->ifname);
>>                  link->ifname = strdup(ifname);
>>                  if (!link->ifname)
>>                          return -ENOMEM;
>> +
>> +                r = link_new_carrier_maps(link);
>> +                if (r < 0)
>> +                        return r;
>>          }
>>
>>          r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu); @@ -2063,6 
>> +2396,39 @@ int link_save(Link *link) {
>>                          llmnr_support_to_string(link->network->llmnr));
>>          }
>>
>> +        if (!hashmap_isempty(link->bound_to_links)) {
>> +                Link *carrier;
>> +                Iterator i;
>> +                bool space = false;
>> +
>> +                fputs("CARRIER_BOUND_TO=", f);
>> +                HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
>> +                        if (space)
>> +                                fputc(' ', f);
>> +                        fputs(carrier->ifname, f);
>> +                        space = true;
>> +                }
>> +
>> +                fputs("\n", f);
>> +        }
>> +
>> +        if (!hashmap_isempty(link->bound_by_links)) {
>> +                Link *carrier;
>> +                Iterator i;
>> +                bool space = false;
>> +
>> +                fputs("CARRIER_BOUND_BY=", f);
>> +                space = false;
>> +                HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
>> +                        if (space)
>> +                                fputc(' ', f);
>> +                        fputs(carrier->ifname, f);
>> +                        space = true;
>> +                }
>> +
>> +                fputs("\n", f);
>> +        }
>> +
>>          if (link->dhcp_lease) {
>>                  assert(link->network);
>>
>> diff --git a/src/network/networkd-link.h 
>> b/src/network/networkd-link.h index cec158e..479098c 100644
>> --- a/src/network/networkd-link.h
>> +++ b/src/network/networkd-link.h
>> @@ -85,6 +85,9 @@ struct Link {
>>
>>          sd_lldp *lldp;
>>          char *lldp_file;
>> +
>> +        Hashmap *bound_by_links;
>> +        Hashmap *bound_to_links;
>>  };
>>
>>  Link *link_unref(Link *link);
>> diff --git a/src/network/networkd-network-gperf.gperf
>> b/src/network/networkd-network-gperf.gperf
>> index fc277df..b0c23a7 100644
>> --- a/src/network/networkd-network-gperf.gperf
>> +++ b/src/network/networkd-network-gperf.gperf
>> @@ -48,6 +48,7 @@ Network.LLMNR,               config_parse_llmnr,           
>>       0,
>>  Network.NTP,                 config_parse_strv,                  0,         
>>                     offsetof(Network, ntp)
>>  Network.IPForward,           config_parse_address_family_boolean,0,         
>>                     offsetof(Network, ip_forward)
>>  Network.IPMasquerade,        config_parse_bool,                  0,         
>>                     offsetof(Network, ip_masquerade)
>> +Network.BindCarrier,         config_parse_strv,                  0,         
>>                     offsetof(Network, bind_carrier)
>>  Address.Address,             config_parse_address,               0,         
>>                     0
>>  Address.Peer,                config_parse_address,               0,         
>>                     0
>>  Address.Broadcast,           config_parse_broadcast,             0,         
>>                     0
>> diff --git a/src/network/networkd-network.c 
>> b/src/network/networkd-network.c index 35ac064..3be993c 100644
>> --- a/src/network/networkd-network.c
>> +++ b/src/network/networkd-network.c
>> @@ -209,6 +209,7 @@ void network_free(Network *network) {
>>          strv_free(network->ntp);
>>          strv_free(network->dns);
>>          strv_free(network->domains);
>> +        strv_free(network->bind_carrier);
>>
>>          netdev_unref(network->bridge);
>>
>> diff --git a/src/network/networkd.h b/src/network/networkd.h index 
>> bdb2f20..e75746f 100644
>> --- a/src/network/networkd.h
>> +++ b/src/network/networkd.h
>> @@ -151,7 +151,7 @@ struct Network {
>>          Hashmap *fdb_entries_by_section;
>>
>>          bool wildcard_domain;
>> -        char **domains, **dns, **ntp;
>> +        char **domains, **dns, **ntp, **bind_carrier;
>>
>>          LLMNRSupport llmnr;
>>
>> diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h 
>> index
>> 027730d..4d96c86 100644
>> --- a/src/systemd/sd-network.h
>> +++ b/src/systemd/sd-network.h
>> @@ -116,6 +116,12 @@ int sd_network_link_get_lldp(int ifindex, char 
>> **lldp);
>>  /* Get the DNS domain names for a given link. */  int 
>> sd_network_link_get_domains(int ifindex, char ***domains);
>>
>> +/* Get the CARRIERS to which current link is bound to. */ int 
>> +sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
>> +
>> +/* Get the CARRIERS that are bound to current link. */ int 
>> +sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
>> +
>>  /* Returns whether or not domains that don't match any link should be 
>> resolved
>>   * on this link. 1 for yes, 0 for no and negative value for error */ 
>> int sd_network_link_get_wildcard_domain(int ifindex);
>> --
>> 1.9.3
>>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to