|
|
7b5541 |
commit 8ca81014a352a125aab38fce2b1302d92c0f5ef2
|
|
|
7b5541 |
Author: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
7b5541 |
Date: Fri Mar 1 15:08:48 2019 +0800
|
|
|
7b5541 |
|
|
|
7b5541 |
rtnl: add team activebackup support
|
|
|
7b5541 |
|
|
|
7b5541 |
This patch add team interface activebackup mode support. As linux team use
|
|
|
7b5541 |
genl netlink message, when we get a rtnl link change notify, we have to setup
|
|
|
7b5541 |
a new genl socket and request the current active port.
|
|
|
7b5541 |
|
|
|
7b5541 |
v2: check nlmsg_len before copy rta_data
|
|
|
7b5541 |
v3: a) Do not make rtnl_buf global as it may be freed by calling rtnl_close()
|
|
|
7b5541 |
while we are using it in rtnl_link_status()
|
|
|
7b5541 |
b) Reorder declarations of variables as reversed Christmas tree for
|
|
|
7b5541 |
function rtnl_link_status()
|
|
|
7b5541 |
c) remove rtnl_len
|
|
|
7b5541 |
v4: Remove the first !rtnl_buf check in rtnl_link_status as it's alway true
|
|
|
7b5541 |
v5: a) Re-order {nl, rtnl}_open and add function nl_close()
|
|
|
7b5541 |
b) revert the v3_{a,c}, v4 changes, use nl_close to close genl fd
|
|
|
7b5541 |
c) do not use len in get_team_active_iface() as it may mislead reader
|
|
|
7b5541 |
|
|
|
7b5541 |
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
7b5541 |
|
|
|
7b5541 |
diff --git a/missing.h b/missing.h
|
|
|
7b5541 |
index 2f7adb9..8f92079 100644
|
|
|
7b5541 |
--- a/missing.h
|
|
|
7b5541 |
+++ b/missing.h
|
|
|
7b5541 |
@@ -118,6 +118,22 @@ enum {
|
|
|
7b5541 |
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
|
|
|
7b5541 |
#endif /*IFLA_BOND_MAX*/
|
|
|
7b5541 |
|
|
|
7b5541 |
+#ifndef NLA_TYPE_MAX
|
|
|
7b5541 |
+enum {
|
|
|
7b5541 |
+ NLA_UNSPEC,
|
|
|
7b5541 |
+ NLA_U8,
|
|
|
7b5541 |
+ NLA_U16,
|
|
|
7b5541 |
+ NLA_U32,
|
|
|
7b5541 |
+ NLA_U64,
|
|
|
7b5541 |
+ NLA_STRING,
|
|
|
7b5541 |
+ NLA_FLAG,
|
|
|
7b5541 |
+ NLA_MSECS,
|
|
|
7b5541 |
+ NLA_NESTED,
|
|
|
7b5541 |
+ __NLA_TYPE_MAX,
|
|
|
7b5541 |
+};
|
|
|
7b5541 |
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
|
|
|
7b5541 |
+#endif /*NLA_TYPE_MAX*/
|
|
|
7b5541 |
+
|
|
|
7b5541 |
#ifdef __UCLIBC__
|
|
|
7b5541 |
|
|
|
7b5541 |
#if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && \
|
|
|
7b5541 |
diff --git a/phc2sys.8 b/phc2sys.8
|
|
|
7b5541 |
index 45cb0e3..b3a3de3 100644
|
|
|
7b5541 |
--- a/phc2sys.8
|
|
|
7b5541 |
+++ b/phc2sys.8
|
|
|
7b5541 |
@@ -108,9 +108,9 @@ together with the
|
|
|
7b5541 |
option, the master clock is used only to correct the offset by whole number of
|
|
|
7b5541 |
seconds, which cannot be fixed with PPS alone. Not compatible with the
|
|
|
7b5541 |
.B \-a
|
|
|
7b5541 |
-option. This option does not support bonded interface (e.g. bond0). If
|
|
|
7b5541 |
+option. This option does not support bonded interface (e.g. bond0, team0). If
|
|
|
7b5541 |
.B ptp4l
|
|
|
7b5541 |
-has a port on an active-backup bond interface, the
|
|
|
7b5541 |
+has a port on an active-backup bond or team interface, the
|
|
|
7b5541 |
.B \-a
|
|
|
7b5541 |
option can be used to track the active interface.
|
|
|
7b5541 |
.TP
|
|
|
7b5541 |
diff --git a/rtnl.c b/rtnl.c
|
|
|
7b5541 |
index f9a572b..e3758b3 100644
|
|
|
7b5541 |
--- a/rtnl.c
|
|
|
7b5541 |
+++ b/rtnl.c
|
|
|
7b5541 |
@@ -20,6 +20,8 @@
|
|
|
7b5541 |
#include <sys/socket.h> /* Must come before linux/netlink.h on some systems. */
|
|
|
7b5541 |
#include <linux/netlink.h>
|
|
|
7b5541 |
#include <linux/rtnetlink.h>
|
|
|
7b5541 |
+#include <linux/genetlink.h>
|
|
|
7b5541 |
+#include <linux/if_team.h>
|
|
|
7b5541 |
#include <net/if.h>
|
|
|
7b5541 |
#include <stdio.h>
|
|
|
7b5541 |
#include <stdlib.h>
|
|
|
7b5541 |
@@ -30,8 +32,39 @@
|
|
|
7b5541 |
#include "print.h"
|
|
|
7b5541 |
#include "rtnl.h"
|
|
|
7b5541 |
|
|
|
7b5541 |
+#define BUF_SIZE 4096
|
|
|
7b5541 |
+#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
|
|
|
7b5541 |
+
|
|
|
7b5541 |
static int rtnl_len;
|
|
|
7b5541 |
static char *rtnl_buf;
|
|
|
7b5541 |
+static int get_team_active_iface(int master_index);
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static int nl_close(int fd)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ return close(fd);
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static int nl_open(int family)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ int fd;
|
|
|
7b5541 |
+ struct sockaddr_nl sa;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ memset(&sa, 0, sizeof(sa));
|
|
|
7b5541 |
+ sa.nl_family = AF_NETLINK;
|
|
|
7b5541 |
+ sa.nl_groups = RTNLGRP_LINK;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ fd = socket(AF_NETLINK, SOCK_RAW, family);
|
|
|
7b5541 |
+ if (fd < 0) {
|
|
|
7b5541 |
+ pr_err("failed to open netlink socket: %m");
|
|
|
7b5541 |
+ return -1;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) {
|
|
|
7b5541 |
+ pr_err("failed to bind netlink socket: %m");
|
|
|
7b5541 |
+ close(fd);
|
|
|
7b5541 |
+ return -1;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+ return fd;
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
|
|
|
7b5541 |
int rtnl_close(int fd)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
@@ -40,7 +73,12 @@ int rtnl_close(int fd)
|
|
|
7b5541 |
rtnl_buf = NULL;
|
|
|
7b5541 |
rtnl_len = 0;
|
|
|
7b5541 |
}
|
|
|
7b5541 |
- return close(fd);
|
|
|
7b5541 |
+ return nl_close(fd);
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+int rtnl_open(void)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ return nl_open(NETLINK_ROUTE);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
static void rtnl_get_ts_device_callback(void *ctx, int linkup, int ts_index)
|
|
|
7b5541 |
@@ -116,14 +154,24 @@ int rtnl_link_query(int fd, char *device)
|
|
|
7b5541 |
return 0;
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
-static inline __u32 rta_getattr_u32(const struct rtattr *rta)
|
|
|
7b5541 |
+static inline __u8 rta_getattr_u8(struct rtattr *rta)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ return *(__u8 *)RTA_DATA(rta);
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static inline __u16 rta_getattr_u16(struct rtattr *rta)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ return *(__u16 *)RTA_DATA(rta);
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static inline __u32 rta_getattr_u32(struct rtattr *rta)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
return *(__u32 *)RTA_DATA(rta);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
-static inline const char *rta_getattr_str(const struct rtattr *rta)
|
|
|
7b5541 |
+static inline char *rta_getattr_str(struct rtattr *rta)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
- return (const char *)RTA_DATA(rta);
|
|
|
7b5541 |
+ return (char *)RTA_DATA(rta);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
|
|
7b5541 |
@@ -150,12 +198,12 @@ static inline int rtnl_nested_rtattr_parse(struct rtattr *tb[], int max, struct
|
|
|
7b5541 |
return rtnl_rtattr_parse(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
-static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
|
7b5541 |
+static int rtnl_linkinfo_parse(int master_index, struct rtattr *rta)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
- int index = -1;
|
|
|
7b5541 |
- const char *kind;
|
|
|
7b5541 |
struct rtattr *linkinfo[IFLA_INFO_MAX];
|
|
|
7b5541 |
struct rtattr *bond[IFLA_BOND_MAX];
|
|
|
7b5541 |
+ int index = -1;
|
|
|
7b5541 |
+ char *kind;
|
|
|
7b5541 |
|
|
|
7b5541 |
if (rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta) < 0)
|
|
|
7b5541 |
return -1;
|
|
|
7b5541 |
@@ -172,6 +220,8 @@ static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
|
7b5541 |
if (bond[IFLA_BOND_ACTIVE_SLAVE]) {
|
|
|
7b5541 |
index = rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
+ } else if (kind && !strncmp(kind, "team", 4)) {
|
|
|
7b5541 |
+ index = get_team_active_iface(master_index);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
}
|
|
|
7b5541 |
return index;
|
|
|
7b5541 |
@@ -179,18 +229,18 @@ static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
|
7b5541 |
|
|
|
7b5541 |
int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
+ struct rtattr *tb[IFLA_MAX+1];
|
|
|
7b5541 |
+ struct ifinfomsg *info = NULL;
|
|
|
7b5541 |
int index, len, link_up;
|
|
|
7b5541 |
- int slave_index = -1;
|
|
|
7b5541 |
- struct iovec iov;
|
|
|
7b5541 |
struct sockaddr_nl sa;
|
|
|
7b5541 |
- struct msghdr msg;
|
|
|
7b5541 |
+ int slave_index = -1;
|
|
|
7b5541 |
struct nlmsghdr *nh;
|
|
|
7b5541 |
- struct ifinfomsg *info = NULL;
|
|
|
7b5541 |
- struct rtattr *tb[IFLA_MAX+1];
|
|
|
7b5541 |
+ struct msghdr msg;
|
|
|
7b5541 |
+ struct iovec iov;
|
|
|
7b5541 |
|
|
|
7b5541 |
index = if_nametoindex(device);
|
|
|
7b5541 |
if (!rtnl_buf) {
|
|
|
7b5541 |
- rtnl_len = 4096;
|
|
|
7b5541 |
+ rtnl_len = BUF_SIZE;
|
|
|
7b5541 |
rtnl_buf = malloc(rtnl_len);
|
|
|
7b5541 |
if (!rtnl_buf) {
|
|
|
7b5541 |
pr_err("rtnl: low memory");
|
|
|
7b5541 |
@@ -246,7 +296,7 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
|
7b5541 |
IFLA_PAYLOAD(nh));
|
|
|
7b5541 |
|
|
|
7b5541 |
if (tb[IFLA_LINKINFO])
|
|
|
7b5541 |
- slave_index = rtnl_linkinfo_parse(tb[IFLA_LINKINFO]);
|
|
|
7b5541 |
+ slave_index = rtnl_linkinfo_parse(index, tb[IFLA_LINKINFO]);
|
|
|
7b5541 |
|
|
|
7b5541 |
if (cb)
|
|
|
7b5541 |
cb(ctx, link_up, slave_index);
|
|
|
7b5541 |
@@ -255,24 +305,164 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
|
7b5541 |
return 0;
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
-int rtnl_open(void)
|
|
|
7b5541 |
+static int genl_send_msg(int fd, int family_id, int genl_cmd, int genl_version,
|
|
|
7b5541 |
+ int rta_type, void *rta_data, int rta_len)
|
|
|
7b5541 |
{
|
|
|
7b5541 |
- int fd;
|
|
|
7b5541 |
- struct sockaddr_nl sa;
|
|
|
7b5541 |
+ struct sockaddr_nl daddr;
|
|
|
7b5541 |
+ struct genlmsghdr *gnlh;
|
|
|
7b5541 |
+ struct nlmsghdr *nlh;
|
|
|
7b5541 |
+ struct rtattr *attr;
|
|
|
7b5541 |
+ char msg[BUF_SIZE];
|
|
|
7b5541 |
|
|
|
7b5541 |
- memset(&sa, 0, sizeof(sa));
|
|
|
7b5541 |
- sa.nl_family = AF_NETLINK;
|
|
|
7b5541 |
- sa.nl_groups = RTNLGRP_LINK;
|
|
|
7b5541 |
+ memset(&daddr, 0, sizeof(daddr));
|
|
|
7b5541 |
+ daddr.nl_family = AF_NETLINK;
|
|
|
7b5541 |
|
|
|
7b5541 |
- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
|
7b5541 |
- if (fd < 0) {
|
|
|
7b5541 |
- pr_err("failed to open netlink socket: %m");
|
|
|
7b5541 |
+ memset(&msg, 0, sizeof(msg));
|
|
|
7b5541 |
+ nlh = (struct nlmsghdr *) msg;
|
|
|
7b5541 |
+ nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
|
|
|
7b5541 |
+ nlh->nlmsg_type = family_id;
|
|
|
7b5541 |
+ nlh->nlmsg_flags = NLM_F_REQUEST;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh);
|
|
|
7b5541 |
+ gnlh->cmd = genl_cmd;
|
|
|
7b5541 |
+ gnlh->version = genl_version;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (rta_data && rta_len > 0) {
|
|
|
7b5541 |
+ attr = (struct rtattr *) GENLMSG_DATA(msg);
|
|
|
7b5541 |
+ attr->rta_type = rta_type;
|
|
|
7b5541 |
+ attr->rta_len = RTA_LENGTH(rta_len);
|
|
|
7b5541 |
+ nlh->nlmsg_len += NLMSG_ALIGN(attr->rta_len);
|
|
|
7b5541 |
+ if (nlh->nlmsg_len < sizeof(msg))
|
|
|
7b5541 |
+ memcpy(RTA_DATA(attr), rta_data, rta_len);
|
|
|
7b5541 |
+ else
|
|
|
7b5541 |
+ return -1;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ return sendto(fd, &msg, nlh->nlmsg_len, 0,
|
|
|
7b5541 |
+ (struct sockaddr *)&daddr, sizeof(daddr));
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static int genl_get_family_id(int fd, void *family_name)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ struct rtattr *tb[CTRL_ATTR_MAX+1];
|
|
|
7b5541 |
+ struct nlmsghdr *nlh;
|
|
|
7b5541 |
+ struct rtattr *attr;
|
|
|
7b5541 |
+ char msg[BUF_SIZE];
|
|
|
7b5541 |
+ int len, gf_id;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ len = genl_send_msg(fd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1,
|
|
|
7b5541 |
+ CTRL_ATTR_FAMILY_NAME, family_name,
|
|
|
7b5541 |
+ strlen(family_name) + 1);
|
|
|
7b5541 |
+ if (len < 0)
|
|
|
7b5541 |
+ return len;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ len = recv(fd, &msg, sizeof(msg), 0);
|
|
|
7b5541 |
+ if (len < 0)
|
|
|
7b5541 |
+ return len;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ nlh = (struct nlmsghdr *) msg;
|
|
|
7b5541 |
+ if (nlh->nlmsg_type == NLMSG_ERROR || !NLMSG_OK(nlh, len))
|
|
|
7b5541 |
return -1;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ attr = (struct rtattr *) GENLMSG_DATA(msg);
|
|
|
7b5541 |
+ rtnl_rtattr_parse(tb, CTRL_ATTR_MAX, attr, NLMSG_PAYLOAD(nlh, GENL_HDRLEN));
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (tb[CTRL_ATTR_FAMILY_ID])
|
|
|
7b5541 |
+ gf_id = rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
|
|
|
7b5541 |
+ else
|
|
|
7b5541 |
+ gf_id = -1;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ return gf_id;
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static int parase_team_list_option(struct rtattr *attr)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ struct rtattr *tb[TEAM_ATTR_OPTION_MAX+1];
|
|
|
7b5541 |
+ int len = RTA_PAYLOAD(attr);
|
|
|
7b5541 |
+ const char *optname = "";
|
|
|
7b5541 |
+ const char *mode = "";
|
|
|
7b5541 |
+ int active_index = -1;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ for (attr = RTA_DATA(attr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
|
|
|
7b5541 |
+ rtnl_nested_rtattr_parse(tb, TEAM_ATTR_OPTION_MAX, attr);
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (tb[TEAM_ATTR_OPTION_NAME])
|
|
|
7b5541 |
+ optname = rta_getattr_str(tb[TEAM_ATTR_OPTION_NAME]);
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (!strcmp(optname, "mode") && tb[TEAM_ATTR_OPTION_TYPE] &&
|
|
|
7b5541 |
+ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_STRING)
|
|
|
7b5541 |
+ mode = rta_getattr_str(tb[TEAM_ATTR_OPTION_DATA]);
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (!strcmp(optname, "activeport") && tb[TEAM_ATTR_OPTION_TYPE] &&
|
|
|
7b5541 |
+ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_U32)
|
|
|
7b5541 |
+ active_index = rta_getattr_u32(tb[TEAM_ATTR_OPTION_DATA]);
|
|
|
7b5541 |
}
|
|
|
7b5541 |
- if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) {
|
|
|
7b5541 |
- pr_err("failed to bind netlink socket: %m");
|
|
|
7b5541 |
- close(fd);
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (strcmp(mode, "activebackup")) {
|
|
|
7b5541 |
+ pr_err("team supported only in activebackup mode");
|
|
|
7b5541 |
return -1;
|
|
|
7b5541 |
+ } else {
|
|
|
7b5541 |
+ return active_index;
|
|
|
7b5541 |
}
|
|
|
7b5541 |
- return fd;
|
|
|
7b5541 |
+}
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+static int get_team_active_iface(int master_index)
|
|
|
7b5541 |
+{
|
|
|
7b5541 |
+ struct rtattr *tb[TEAM_ATTR_MAX+1];
|
|
|
7b5541 |
+ struct genlmsghdr *gnlh;
|
|
|
7b5541 |
+ struct nlmsghdr *nlh;
|
|
|
7b5541 |
+ char msg[BUF_SIZE];
|
|
|
7b5541 |
+ int fd, gf_id, len;
|
|
|
7b5541 |
+ int index = -1;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ fd = nl_open(NETLINK_GENERIC);
|
|
|
7b5541 |
+ if (fd < 0)
|
|
|
7b5541 |
+ return fd;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ gf_id = genl_get_family_id(fd, TEAM_GENL_NAME);
|
|
|
7b5541 |
+ if (gf_id < 0) {
|
|
|
7b5541 |
+ pr_err("get genl family failed");
|
|
|
7b5541 |
+ goto no_info;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ len = genl_send_msg(fd, gf_id, TEAM_CMD_OPTIONS_GET,
|
|
|
7b5541 |
+ TEAM_GENL_VERSION, TEAM_ATTR_TEAM_IFINDEX,
|
|
|
7b5541 |
+ &master_index, sizeof(master_index));
|
|
|
7b5541 |
+ if (len < 0) {
|
|
|
7b5541 |
+ pr_err("send team info request failed: %m");
|
|
|
7b5541 |
+ goto no_info;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ len = recv(fd, msg, sizeof(msg), 0);
|
|
|
7b5541 |
+ if (len < 0) {
|
|
|
7b5541 |
+ pr_err("recv team info failed: %m");
|
|
|
7b5541 |
+ goto no_info;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ nlh = (struct nlmsghdr *) msg;
|
|
|
7b5541 |
+ for ( ; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
|
|
|
7b5541 |
+ if (nlh->nlmsg_type != gf_id)
|
|
|
7b5541 |
+ continue;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh);
|
|
|
7b5541 |
+ if (gnlh->cmd != TEAM_CMD_OPTIONS_GET)
|
|
|
7b5541 |
+ continue;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ rtnl_rtattr_parse(tb, TEAM_ATTR_MAX, (struct rtattr *)GENLMSG_DATA(msg),
|
|
|
7b5541 |
+ NLMSG_PAYLOAD(nlh, GENL_HDRLEN));
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (tb[TEAM_ATTR_TEAM_IFINDEX] &&
|
|
|
7b5541 |
+ master_index != rta_getattr_u32(tb[TEAM_ATTR_TEAM_IFINDEX]))
|
|
|
7b5541 |
+ continue;
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ if (tb[TEAM_ATTR_LIST_OPTION]) {
|
|
|
7b5541 |
+ index = parase_team_list_option(tb[TEAM_ATTR_LIST_OPTION]);
|
|
|
7b5541 |
+ break;
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+ }
|
|
|
7b5541 |
+
|
|
|
7b5541 |
+ return index;
|
|
|
7b5541 |
+no_info:
|
|
|
7b5541 |
+ nl_close(fd);
|
|
|
7b5541 |
+ return -1;
|
|
|
7b5541 |
}
|
|
|
7b5541 |
commit d8eafa6a39a609597e6c1ce44d616ba6f33c27f8
|
|
|
7b5541 |
Author: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
7b5541 |
Date: Wed Mar 20 14:44:13 2019 +0800
|
|
|
7b5541 |
|
|
|
7b5541 |
port: should check the new phc_index before switching
|
|
|
7b5541 |
|
|
|
7b5541 |
In logic, when we want to switch phc, we should check if the new phc
|
|
|
7b5541 |
index is valid instead of checking the previous one.
|
|
|
7b5541 |
|
|
|
7b5541 |
In reality, if we use linux team interface with activebackup mode. As
|
|
|
7b5541 |
teamd is a userspace tool, it sets the new slave as active port after
|
|
|
7b5541 |
receiving link change message. If we set current active port down and
|
|
|
7b5541 |
another slave up. There is a race that we receive the new slave's link
|
|
|
7b5541 |
up message while active port(ts_index) is still the old one. This means
|
|
|
7b5541 |
we may use a link down interface as ts_index and get phc_index with -1.
|
|
|
7b5541 |
|
|
|
7b5541 |
If we update the p->phc_index to -1, there will be no possibility to
|
|
|
7b5541 |
change it back to other value as we swith phc only when p->phc_index >= 0.
|
|
|
7b5541 |
|
|
|
7b5541 |
With this fix, we will not switch phc_index until receiving the real
|
|
|
7b5541 |
active port(p->iface->ts_info.phc_index >= 0) update message.
|
|
|
7b5541 |
|
|
|
7b5541 |
Reported-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
7b5541 |
Fixes: 536a71031d5c ("ptp4l: use ts label to get ts info")
|
|
|
7b5541 |
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
|
|
|
7b5541 |
|
|
|
7b5541 |
diff --git a/port.c b/port.c
|
|
|
7b5541 |
index ad9554f..49c6f76 100644
|
|
|
7b5541 |
--- a/port.c
|
|
|
7b5541 |
+++ b/port.c
|
|
|
7b5541 |
@@ -2442,7 +2442,7 @@ void port_link_status(void *ctx, int linkup, int ts_index)
|
|
|
7b5541 |
sk_get_ts_info(p->iface->ts_label, &p->iface->ts_info);
|
|
|
7b5541 |
|
|
|
7b5541 |
/* Only switch phc with HW time stamping mode */
|
|
|
7b5541 |
- if (p->phc_index >= 0 && p->iface->ts_info.valid) {
|
|
|
7b5541 |
+ if (p->iface->ts_info.valid && p->iface->ts_info.phc_index >= 0) {
|
|
|
7b5541 |
required_modes = clock_required_modes(p->clock);
|
|
|
7b5541 |
if ((p->iface->ts_info.so_timestamping & required_modes) != required_modes) {
|
|
|
7b5541 |
pr_err("interface '%s' does not support requested "
|
|
|
7b5541 |
commit ecfbea2dac2312cb61aa5d2fe1646ee4c6b18643
|
|
|
7b5541 |
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
7b5541 |
Date: Thu Mar 21 15:44:32 2019 +0100
|
|
|
7b5541 |
|
|
|
7b5541 |
rtnl: close file descriptor in get_team_active_iface()
|
|
|
7b5541 |
|
|
|
7b5541 |
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
7b5541 |
|
|
|
7b5541 |
diff --git a/rtnl.c b/rtnl.c
|
|
|
7b5541 |
index e3758b3..59ed0ec 100644
|
|
|
7b5541 |
--- a/rtnl.c
|
|
|
7b5541 |
+++ b/rtnl.c
|
|
|
7b5541 |
@@ -461,8 +461,7 @@ static int get_team_active_iface(int master_index)
|
|
|
7b5541 |
}
|
|
|
7b5541 |
}
|
|
|
7b5541 |
|
|
|
7b5541 |
- return index;
|
|
|
7b5541 |
no_info:
|
|
|
7b5541 |
nl_close(fd);
|
|
|
7b5541 |
- return -1;
|
|
|
7b5541 |
+ return index;
|
|
|
7b5541 |
}
|