Support link operstate and linkmode

This commit is contained in:
Thomas Graf 2007-12-19 22:03:44 +01:00
parent 4649886288
commit 3ad4665be2
6 changed files with 188 additions and 10 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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 *,

View file

@ -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

View file

@ -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.

View file

@ -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)