Support link operstate and linkmode
This commit is contained in:
parent
4649886288
commit
3ad4665be2
6 changed files with 188 additions and 10 deletions
|
@ -19,6 +19,8 @@
|
|||
#ifndef _LINUX_IF_H
|
||||
#define _LINUX_IF_H
|
||||
|
||||
#include <linux/types.h> /* for "__kernel_caddr_t" et al */
|
||||
|
||||
#define IFNAMSIZ 16
|
||||
|
||||
/* Standard interface flags (netdevice->flags). */
|
||||
|
@ -28,7 +30,7 @@
|
|||
#define IFF_LOOPBACK 0x8 /* is a loopback net */
|
||||
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
|
||||
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
|
||||
#define IFF_RUNNING 0x40 /* interface running and carrier ok */
|
||||
#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */
|
||||
#define IFF_NOARP 0x80 /* no ARP protocol */
|
||||
#define IFF_PROMISC 0x100 /* receive all packets */
|
||||
#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
|
||||
|
@ -38,17 +40,27 @@
|
|||
|
||||
#define IFF_MULTICAST 0x1000 /* Supports multicast */
|
||||
|
||||
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
|
||||
|
||||
#define IFF_PORTSEL 0x2000 /* can set media type */
|
||||
#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
|
||||
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
|
||||
|
||||
#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
|
||||
#define IFF_DORMANT 0x20000 /* driver signals dormant */
|
||||
|
||||
#define IFF_ECHO 0x40000 /* echo sent packets */
|
||||
|
||||
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
|
||||
IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
|
||||
|
||||
/* Private (from user) interface flags (netdevice->priv_flags). */
|
||||
#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */
|
||||
#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */
|
||||
#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */
|
||||
#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */
|
||||
#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */
|
||||
#define IFF_BONDING 0x20 /* bonding master or slave */
|
||||
#define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */
|
||||
#define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */
|
||||
|
||||
#define IF_GET_IFACE 0x0001 /* for querying only */
|
||||
#define IF_GET_PROTO 0x0002
|
||||
|
@ -77,6 +89,22 @@
|
|||
#define IF_PROTO_FR_ETH_PVC 0x200B
|
||||
#define IF_PROTO_RAW 0x200C /* RAW Socket */
|
||||
|
||||
/* RFC 2863 operational status */
|
||||
enum {
|
||||
IF_OPER_UNKNOWN,
|
||||
IF_OPER_NOTPRESENT,
|
||||
IF_OPER_DOWN,
|
||||
IF_OPER_LOWERLAYERDOWN,
|
||||
IF_OPER_TESTING,
|
||||
IF_OPER_DORMANT,
|
||||
IF_OPER_UP,
|
||||
};
|
||||
|
||||
/* link modes */
|
||||
enum {
|
||||
IF_LINK_MODE_DEFAULT,
|
||||
IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
|
||||
};
|
||||
|
||||
/*
|
||||
* Device mapping structure. I'd just gone off and designed a
|
||||
|
@ -99,4 +127,5 @@ struct ifmap
|
|||
/* 3 bytes spare */
|
||||
};
|
||||
|
||||
|
||||
#endif /* _LINUX_IF_H */
|
||||
|
|
|
@ -173,6 +173,8 @@ struct rtnl_link
|
|||
struct rtnl_link_map l_map;
|
||||
uint64_t l_stats[RTNL_LINK_STATS_MAX+1];
|
||||
uint32_t l_flag_mask;
|
||||
uint8_t l_operstate;
|
||||
uint8_t l_linkmode;
|
||||
};
|
||||
|
||||
struct rtnl_ncacheinfo
|
||||
|
|
|
@ -36,6 +36,7 @@ extern int nl_addr_shared(struct nl_addr *);
|
|||
|
||||
extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *);
|
||||
extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *);
|
||||
extern int nl_addr_iszero(struct nl_addr *);
|
||||
extern int nl_addr_valid(char *, int);
|
||||
extern int nl_addr_guess_family(struct nl_addr *);
|
||||
extern int nl_addr_fill_sockaddr(struct nl_addr *,
|
||||
|
|
|
@ -91,6 +91,12 @@ extern int rtnl_link_str2stat(const char *);
|
|||
extern char * rtnl_link_flags2str(int, char *, size_t);
|
||||
extern int rtnl_link_str2flags(const char *);
|
||||
|
||||
extern char * rtnl_link_operstate2str(int, char *, size_t);
|
||||
extern int rtnl_link_str2operstate(const char *);
|
||||
|
||||
extern char * rtnl_link_mode2str(int, char *, size_t);
|
||||
extern int rtnl_link_str2mode(const char *);
|
||||
|
||||
/* Access Functions */
|
||||
extern void rtnl_link_set_qdisc(struct rtnl_link *,
|
||||
const char *);
|
||||
|
@ -142,6 +148,14 @@ extern int rtnl_link_get_link(struct rtnl_link *);
|
|||
extern void rtnl_link_set_master(struct rtnl_link *, int);
|
||||
extern int rtnl_link_get_master(struct rtnl_link *);
|
||||
|
||||
extern void rtnl_link_set_operstate(struct rtnl_link *,
|
||||
uint8_t);
|
||||
extern uint8_t rtnl_link_get_operstate(struct rtnl_link *);
|
||||
|
||||
extern void rtnl_link_set_linkmode(struct rtnl_link *,
|
||||
uint8_t);
|
||||
extern uint8_t rtnl_link_get_linkmode(struct rtnl_link *);
|
||||
|
||||
extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
15
lib/addr.c
15
lib/addr.c
|
@ -528,6 +528,21 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
|
|||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the address consists of all zeros
|
||||
* @arg addr Address to look at.
|
||||
*/
|
||||
int nl_addr_iszero(struct nl_addr *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < addr->a_len; i++)
|
||||
if (addr->a_addr[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an address matches a certain family.
|
||||
* @arg addr Address represented as character string.
|
||||
|
|
131
lib/route/link.c
131
lib/route/link.c
|
@ -151,6 +151,8 @@
|
|||
#define LINK_ATTR_ARPTYPE 0x2000
|
||||
#define LINK_ATTR_STATS 0x4000
|
||||
#define LINK_ATTR_CHANGE 0x8000
|
||||
#define LINK_ATTR_OPERSTATE 0x10000
|
||||
#define LINK_ATTR_LINKMODE 0x20000
|
||||
|
||||
static struct nl_cache_ops rtnl_link_ops;
|
||||
static struct nl_object_ops link_obj_ops;
|
||||
|
@ -192,6 +194,8 @@ static struct nla_policy link_policy[IFLA_MAX+1] = {
|
|||
[IFLA_LINK] = { .type = NLA_U32 },
|
||||
[IFLA_WEIGHT] = { .type = NLA_U32 },
|
||||
[IFLA_MASTER] = { .type = NLA_U32 },
|
||||
[IFLA_OPERSTATE]= { .type = NLA_U8 },
|
||||
[IFLA_LINKMODE] = { .type = NLA_U8 },
|
||||
[IFLA_QDISC] = { .type = NLA_STRING,
|
||||
.maxlen = IFQDISCSIZ },
|
||||
[IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) },
|
||||
|
@ -323,6 +327,16 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
|||
link->ce_mask |= LINK_ATTR_MASTER;
|
||||
}
|
||||
|
||||
if (tb[IFLA_OPERSTATE]) {
|
||||
link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]);
|
||||
link->ce_mask |= LINK_ATTR_OPERSTATE;
|
||||
}
|
||||
|
||||
if (tb[IFLA_LINKMODE]) {
|
||||
link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]);
|
||||
link->ce_mask |= LINK_ATTR_LINKMODE;
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *) link, pp);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
@ -356,9 +370,9 @@ static int link_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
|
|||
}
|
||||
|
||||
dp_dump(p, "%s ", nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
|
||||
dp_dump(p, "%s ", link->l_addr ? nl_addr2str(link->l_addr, buf,
|
||||
sizeof(buf)) : "none");
|
||||
dp_dump(p, "mtu %u ", link->l_mtu);
|
||||
|
||||
if (link->l_addr && !nl_addr_iszero(link->l_addr))
|
||||
dp_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf)));
|
||||
|
||||
if (link->ce_mask & LINK_ATTR_MASTER) {
|
||||
struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
|
||||
|
@ -385,7 +399,8 @@ static int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
|
|||
line = link_dump_brief(obj, p);
|
||||
dp_new_line(p, line++);
|
||||
|
||||
dp_dump(p, " txqlen %u weight %u ", link->l_txqlen, link->l_weight);
|
||||
dp_dump(p, " mtu %u ", link->l_mtu);
|
||||
dp_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight);
|
||||
|
||||
if (link->ce_mask & LINK_ATTR_QDISC)
|
||||
dp_dump(p, "qdisc %s ", link->l_qdisc);
|
||||
|
@ -396,11 +411,24 @@ static int link_dump_full(struct nl_object *obj, struct nl_dump_params *p)
|
|||
if (link->ce_mask & LINK_ATTR_IFINDEX)
|
||||
dp_dump(p, "index %u ", link->l_index);
|
||||
|
||||
if (link->ce_mask & LINK_ATTR_BRD)
|
||||
dp_dump(p, "brd %s", nl_addr2str(link->l_bcast, buf,
|
||||
sizeof(buf)));
|
||||
|
||||
dp_dump(p, "\n");
|
||||
dp_new_line(p, line++);
|
||||
|
||||
dp_dump(p, " ");
|
||||
|
||||
if (link->ce_mask & LINK_ATTR_BRD)
|
||||
dp_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf,
|
||||
sizeof(buf)));
|
||||
|
||||
if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
|
||||
link->l_operstate != IF_OPER_UNKNOWN) {
|
||||
rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf));
|
||||
dp_dump(p, "state %s ", buf);
|
||||
}
|
||||
|
||||
dp_dump(p, "mode %s\n",
|
||||
rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf)));
|
||||
|
||||
return line;
|
||||
}
|
||||
|
@ -667,6 +695,8 @@ static int link_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
|
||||
diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
|
||||
diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
|
||||
diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
|
||||
diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
|
||||
diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
|
||||
diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
|
||||
diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
|
||||
|
@ -700,6 +730,8 @@ static struct trans_tbl link_attrs[] = {
|
|||
__ADD(LINK_ATTR_ARPTYPE, arptype)
|
||||
__ADD(LINK_ATTR_STATS, stats)
|
||||
__ADD(LINK_ATTR_CHANGE, change)
|
||||
__ADD(LINK_ATTR_OPERSTATE, operstate)
|
||||
__ADD(LINK_ATTR_LINKMODE, linkmode)
|
||||
};
|
||||
|
||||
static char *link_attrs2str(int attrs, char *buf, size_t len)
|
||||
|
@ -877,6 +909,12 @@ struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *old,
|
|||
if (tmpl->ce_mask & LINK_ATTR_IFNAME)
|
||||
NLA_PUT_STRING(msg, IFLA_IFNAME, tmpl->l_name);
|
||||
|
||||
if (tmpl->ce_mask & LINK_ATTR_OPERSTATE)
|
||||
NLA_PUT_U8(msg, IFLA_OPERSTATE, tmpl->l_operstate);
|
||||
|
||||
if (tmpl->ce_mask & LINK_ATTR_LINKMODE)
|
||||
NLA_PUT_U8(msg, IFLA_LINKMODE, tmpl->l_linkmode);
|
||||
|
||||
return msg;
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -1055,6 +1093,57 @@ int rtnl_link_str2stat(const char *name)
|
|||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Link Operstate Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
static struct trans_tbl link_operstates[] = {
|
||||
__ADD(IF_OPER_UNKNOWN, unknown)
|
||||
__ADD(IF_OPER_NOTPRESENT, notpresent)
|
||||
__ADD(IF_OPER_DOWN, down)
|
||||
__ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
|
||||
__ADD(IF_OPER_TESTING, testing)
|
||||
__ADD(IF_OPER_DORMANT, dormant)
|
||||
__ADD(IF_OPER_UP, up)
|
||||
};
|
||||
|
||||
char *rtnl_link_operstate2str(int st, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(st, buf, len, link_operstates,
|
||||
ARRAY_SIZE(link_operstates));
|
||||
}
|
||||
|
||||
int rtnl_link_str2operstate(const char *name)
|
||||
{
|
||||
return __str2type(name, link_operstates,
|
||||
ARRAY_SIZE(link_operstates));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Link Mode Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
static struct trans_tbl link_modes[] = {
|
||||
__ADD(IF_LINK_MODE_DEFAULT, default)
|
||||
__ADD(IF_LINK_MODE_DORMANT, dormant)
|
||||
};
|
||||
|
||||
char *rtnl_link_mode2str(int st, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
|
||||
}
|
||||
|
||||
int rtnl_link_str2mode(const char *name)
|
||||
{
|
||||
return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
|
@ -1253,6 +1342,34 @@ int rtnl_link_get_master(struct rtnl_link *link)
|
|||
return RTNL_LINK_NOT_FOUND;
|
||||
}
|
||||
|
||||
void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t operstate)
|
||||
{
|
||||
link->l_operstate = operstate;
|
||||
link->ce_mask |= LINK_ATTR_OPERSTATE;
|
||||
}
|
||||
|
||||
uint8_t rtnl_link_get_operstate(struct rtnl_link *link)
|
||||
{
|
||||
if (link->ce_mask & LINK_ATTR_OPERSTATE)
|
||||
return link->l_operstate;
|
||||
else
|
||||
return IF_OPER_UNKNOWN;
|
||||
}
|
||||
|
||||
void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t linkmode)
|
||||
{
|
||||
link->l_linkmode = linkmode;
|
||||
link->ce_mask |= LINK_ATTR_LINKMODE;
|
||||
}
|
||||
|
||||
uint8_t rtnl_link_get_linkmode(struct rtnl_link *link)
|
||||
{
|
||||
if (link->ce_mask & LINK_ATTR_LINKMODE)
|
||||
return link->l_linkmode;
|
||||
else
|
||||
return IF_LINK_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
uint64_t rtnl_link_get_stat(struct rtnl_link *link, int id)
|
||||
{
|
||||
if (id < 0 || id > RTNL_LINK_STATS_MAX)
|
||||
|
|
Loading…
Add table
Reference in a new issue