> -----Original Message-----
> From: Hangbin Liu [mailto:liuhang...@gmail.com]
> Sent: Saturday, July 15, 2017 6:33 AM
> To: linuxptp-devel@lists.sourceforge.net
> Cc: Sushil Kulkarni <sukul...@redhat.com>; Jiri Benc <jb...@redhat.com>
> Subject: [Linuxptp-devel] [PATCHv2 4/9] rtnl: add function rtnl_link_info
> 
> Add function rtnl_link_info() to get bond's active interface. If there is
> no slave interface, then use our own name as ts interface.
> 
> Also add new parameter ts_iface for call back function port_link_status()
> to make aware of interface change.
> 
> Signed-off-by: Hangbin Liu <liuhang...@gmail.com>
> ---
>  port.c |   2 +-
>  rtnl.c | 122
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++-
>  rtnl.h |  10 +++++-
>  3 files changed, 131 insertions(+), 3 deletions(-)
> 
> diff --git a/port.c b/port.c
> index 21ab3ea..834eb45 100644
> --- a/port.c
> +++ b/port.c
> @@ -2221,7 +2221,7 @@ void port_dispatch(struct port *p, enum fsm_event
> event, int mdiff)
>       }
>  }
> 
> -static void port_link_status(void *ctx, int index, int linkup)
> +static void port_link_status(void *ctx, int index, int linkup, char 
> *ts_iface)
>  {
>       struct port *p = ctx;
> 
> diff --git a/rtnl.c b/rtnl.c
> index 04e1918..b499467 100644
> --- a/rtnl.c
> +++ b/rtnl.c
> @@ -31,6 +31,9 @@
> 
>  static int rtnl_len;
>  static char *rtnl_buf;
> +static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr 
> *rta, int len);
> +#define rtnl_nested_rtattr_parse(tb, max, rta) \
> +     (rtnl_rtattr_parse((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
> 
>  int rtnl_close(int fd)
>  {
> @@ -84,6 +87,62 @@ int rtnl_link_query(int fd, unsigned int if_index)
>       return 0;
>  }
> 
> +static inline __u32 rta_getattr_u32(const struct rtattr *rta)
> +{
> +     return *(__u32 *)RTA_DATA(rta);
> +}
> +
> +static inline const char *rta_getattr_str(const struct rtattr *rta)
> +{
> +     return (const char *)RTA_DATA(rta);
> +}
> +
> +static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr 
> *rta, int len)
> +{
> +     unsigned short type;
> +
> +     memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
> +     while (RTA_OK(rta, len)) {
> +             type = rta->rta_type;
> +             if ((type <= max) && (!tb[type]))
> +                     tb[type] = rta;
> +             rta = RTA_NEXT(rta, len);
> +     }
> +     if (len)
> +             fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
> +                     len, rta->rta_len);
> +     return 0;
> +}
> +
> +static int rtnl_linkinfo_parse(struct rtattr *rta, char *device)
> +{
> +     int index;
> +     struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
> +     struct rtattr *bond[IFLA_BOND_MAX + 1];
> +
> +     rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta);
> +
> +     if (linkinfo[IFLA_INFO_KIND]) {
> +             const char *kind = rta_getattr_str(linkinfo[IFLA_INFO_KIND]);
> +
> +             if (kind && !strncmp(kind, "bond", 4) &&
> +                 linkinfo[IFLA_INFO_DATA]) {
> +                     rtnl_nested_rtattr_parse(bond, IFLA_BOND_MAX,
> +                                              linkinfo[IFLA_INFO_DATA]);
> +
> +                     if (bond[IFLA_BOND_ACTIVE_SLAVE]) {
> +                             index =
> rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]);
> +
> +                             if (!if_indextoname(index, device)) {
> +                                     pr_err("failed to get device name: %m");
> +                                     return -1;
> +                             }
> +                     }
> +             }
> +     }
> +     return 0;
> +}
> +
>  int rtnl_link_status(int fd, rtnl_callback cb, void *ctx)
>  {
>       int index, len;
> @@ -92,6 +151,18 @@ int rtnl_link_status(int fd, rtnl_callback cb, void *ctx)
>       struct msghdr msg;
>       struct nlmsghdr *nh;
>       struct ifinfomsg *info = NULL;
> +     char *device;
> +     struct rtattr *tb[IFLA_MAX+1];
> +
> +     if (cb)
> +             device = calloc(1, sizeof(MAX_IFNAME_SIZE + 1));
> +     else
> +             device = (char *)ctx;
> +
> +     if (!device) {
> +             fprintf(stderr, "rtnl: no enought memory for device name\n");
> +             return -1;
> +     }
> 
>       if (!rtnl_buf) {
>               rtnl_len = 4096;
> @@ -140,7 +211,18 @@ int rtnl_link_status(int fd, rtnl_callback cb, void *ctx)
>                       index = info->ifi_index;
>                       pr_debug("interface index %d is %s", index,
>                                info->ifi_flags & IFF_RUNNING ? "up" : "down");
> -                     cb(ctx, index, info->ifi_flags & IFF_RUNNING ? 1 : 0);
> +
> +                     rtnl_rtattr_parse(tb, IFLA_MAX, IFLA_RTA(info),
> +                                       IFLA_PAYLOAD(nh));
> +
> +                     if (tb[IFLA_LINKINFO])
> +                             rtnl_linkinfo_parse(tb[IFLA_LINKINFO], device);
> +
> +                     if (cb) {
> +                             cb(ctx, index, info->ifi_flags & IFF_RUNNING ? 
> 1 :
> 0, device);
> +                             free(device);
> +                     }
> +
>               }
>       }
>       return 0;
> @@ -167,3 +249,41 @@ int rtnl_open(void)
>       }
>       return fd;
>  }
> +
> +int rtnl_link_info(struct interface *iface)
> +{
> +     int fd, index;
> +
> +     index = if_nametoindex(iface->name);
> +
> +     if (index == 0) {
> +             pr_err("failed to get interface %s index: %m", iface->name);
> +             goto no_fd;
> +     }
> +
> +     fd = rtnl_open();
> +     if (fd < 0)
> +             goto no_fd;
> +
> +     if (rtnl_link_query(fd, index))
> +             goto no_info;
> +     if (rtnl_link_status(fd, NULL, iface->ts_iface))
> +             goto no_info;
> +
> +     /* If we do not have a slave, then use our own interface name
> +      * as ts_iface
> +      */
> +     if (iface->ts_iface[0] == '\0')
> +             strncpy(iface->ts_iface, iface->name, MAX_IFNAME_SIZE);
> +

Seems like we're duplicating code here just to maintain a return value?

> +     rtnl_close(fd);
> +     return 0;
> +
> +no_info:
> +     rtnl_close(fd);
> +no_fd:
> +     if (iface->ts_iface[0] == '\0')
> +             strncpy(iface->ts_iface, iface->name, MAX_IFNAME_SIZE);
> +
> +     return -1;
> +}
> diff --git a/rtnl.h b/rtnl.h
> index b4db40e..c382088 100644
> --- a/rtnl.h
> +++ b/rtnl.h
> @@ -20,7 +20,9 @@
>  #ifndef HAVE_RTNL_H
>  #define HAVE_RTNL_H
> 
> -typedef void (*rtnl_callback)(void *ctx, int index, int linkup);
> +#include "config.h"
> +
> +typedef void (*rtnl_callback)(void *ctx, int index, int linkup, char 
> *device);
> 
>  /**
>   * Close a RT netlink socket.
> @@ -52,4 +54,10 @@ int rtnl_link_status(int fd, rtnl_callback cb, void *ctx);
>   */
>  int rtnl_open(void);
> 
> +/**
> + * Get interface link status and ts_iface information
> + * @param iface  struct interface.
> + * @return       Zero on success, or -1 on error.
> + */
> +int rtnl_link_info(struct interface *iface);
>  #endif
> --
> 2.5.5
> 
> 
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Linuxptp-devel mailing list
> Linuxptp-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to