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