From 99dde0b03a7380e29544aceac6e32432632a54dc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 25 Jul 2014 14:33:38 -0500 Subject: [PATCH 1/2] link: update copy of kernel header include/linux/if_link.h The next patch will use some of these defines, so update. Taken from upstream kernel commit bc91b0f07ada5535427373a4e2050877bcc12218, file 'include/uapi/linux/if_link.h'. Signed-off-by: Dan Williams Signed-off-by: Thomas Haller (cherry picked from commit b51815a9dbd8e45fd2558bbe337fb360ca2fd861) Conflicts: include/linux/if_link.h --- include/linux/if_link.h | 194 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 181 insertions(+), 13 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index a753d11..ff95760 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_IF_LINK_H -#define _LINUX_IF_LINK_H +#ifndef _UAPI_LINUX_IF_LINK_H +#define _UAPI_LINUX_IF_LINK_H #include #include @@ -143,12 +143,20 @@ enum { IFLA_NUM_TX_QUEUES, IFLA_NUM_RX_QUEUES, IFLA_CARRIER, + IFLA_PHYS_PORT_ID, + IFLA_CARRIER_CHANGES, __IFLA_MAX }; #define IFLA_MAX (__IFLA_MAX - 1) +/* backwards compatibility for userspace */ +#ifndef __KERNEL__ +#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) +#endif + enum { IFLA_INET_UNSPEC, IFLA_INET_CONF, @@ -195,11 +203,38 @@ enum { IFLA_INET6_MCAST, /* MC things. What of them? */ IFLA_INET6_CACHEINFO, /* time values and max reasm size */ IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ + IFLA_INET6_TOKEN, /* device token */ + IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ __IFLA_INET6_MAX }; #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) +enum in6_addr_gen_mode { + IN6_ADDR_GEN_MODE_EUI64, + IN6_ADDR_GEN_MODE_NONE, +}; + +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + IFLA_BRPORT_LEARNING, /* mac learning */ + IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + struct ifla_cacheinfo { __u32 max_reasm_len; __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ @@ -212,6 +247,8 @@ enum { IFLA_INFO_KIND, IFLA_INFO_DATA, IFLA_INFO_XSTATS, + IFLA_INFO_SLAVE_KIND, + IFLA_INFO_SLAVE_DATA, __IFLA_INFO_MAX, }; @@ -225,6 +262,7 @@ enum { IFLA_VLAN_FLAGS, IFLA_VLAN_EGRESS_QOS, IFLA_VLAN_INGRESS_QOS, + IFLA_VLAN_PROTOCOL, __IFLA_VLAN_MAX, }; @@ -267,6 +305,95 @@ enum macvlan_mode { #define MACVLAN_FLAG_NOPROMISC 1 +/* VXLAN section */ +enum { + IFLA_VXLAN_UNSPEC, + IFLA_VXLAN_ID, + IFLA_VXLAN_GROUP, /* group or remote address */ + IFLA_VXLAN_LINK, + IFLA_VXLAN_LOCAL, + IFLA_VXLAN_TTL, + IFLA_VXLAN_TOS, + IFLA_VXLAN_LEARNING, + IFLA_VXLAN_AGEING, + IFLA_VXLAN_LIMIT, + IFLA_VXLAN_PORT_RANGE, /* source port */ + IFLA_VXLAN_PROXY, + IFLA_VXLAN_RSC, + IFLA_VXLAN_L2MISS, + IFLA_VXLAN_L3MISS, + IFLA_VXLAN_PORT, /* destination port */ + IFLA_VXLAN_GROUP6, + IFLA_VXLAN_LOCAL6, + IFLA_VXLAN_UDP_CSUM, + IFLA_VXLAN_UDP_ZERO_CSUM6_TX, + IFLA_VXLAN_UDP_ZERO_CSUM6_RX, + __IFLA_VXLAN_MAX +}; +#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) + +struct ifla_vxlan_port_range { + __be16 low; + __be16 high; +}; + +/* Bonding section */ + +enum { + IFLA_BOND_UNSPEC, + IFLA_BOND_MODE, + IFLA_BOND_ACTIVE_SLAVE, + IFLA_BOND_MIIMON, + IFLA_BOND_UPDELAY, + IFLA_BOND_DOWNDELAY, + IFLA_BOND_USE_CARRIER, + IFLA_BOND_ARP_INTERVAL, + IFLA_BOND_ARP_IP_TARGET, + IFLA_BOND_ARP_VALIDATE, + IFLA_BOND_ARP_ALL_TARGETS, + IFLA_BOND_PRIMARY, + IFLA_BOND_PRIMARY_RESELECT, + IFLA_BOND_FAIL_OVER_MAC, + IFLA_BOND_XMIT_HASH_POLICY, + IFLA_BOND_RESEND_IGMP, + IFLA_BOND_NUM_PEER_NOTIF, + IFLA_BOND_ALL_SLAVES_ACTIVE, + IFLA_BOND_MIN_LINKS, + IFLA_BOND_LP_INTERVAL, + IFLA_BOND_PACKETS_PER_SLAVE, + IFLA_BOND_AD_LACP_RATE, + IFLA_BOND_AD_SELECT, + IFLA_BOND_AD_INFO, + __IFLA_BOND_MAX, +}; + +#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) + +enum { + IFLA_BOND_AD_INFO_UNSPEC, + IFLA_BOND_AD_INFO_AGGREGATOR, + IFLA_BOND_AD_INFO_NUM_PORTS, + IFLA_BOND_AD_INFO_ACTOR_KEY, + IFLA_BOND_AD_INFO_PARTNER_KEY, + IFLA_BOND_AD_INFO_PARTNER_MAC, + __IFLA_BOND_AD_INFO_MAX, +}; + +#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) + +enum { + IFLA_BOND_SLAVE_UNSPEC, + IFLA_BOND_SLAVE_STATE, + IFLA_BOND_SLAVE_MII_STATUS, + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, + IFLA_BOND_SLAVE_PERM_HWADDR, + IFLA_BOND_SLAVE_QUEUE_ID, + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, + __IFLA_BOND_SLAVE_MAX, +}; + +#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) + /* SR-IOV virtual function management section */ enum { @@ -281,8 +408,10 @@ enum { IFLA_VF_UNSPEC, IFLA_VF_MAC, /* Hardware queue specific attributes */ IFLA_VF_VLAN, - IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */ IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ + IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ + IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */ __IFLA_VF_MAX, }; @@ -304,22 +433,28 @@ struct ifla_vf_tx_rate { __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ }; +struct ifla_vf_rate { + __u32 vf; + __u32 min_tx_rate; /* Min Bandwidth in Mbps */ + __u32 max_tx_rate; /* Max Bandwidth in Mbps */ +}; + struct ifla_vf_spoofchk { __u32 vf; __u32 setting; }; -#ifdef __KERNEL__ -/* We don't want this structure exposed to user space */ -struct ifla_vf_info { +enum { + IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE, /* link always up */ + IFLA_VF_LINK_STATE_DISABLE, /* link always down */ + __IFLA_VF_LINK_STATE_MAX, +}; + +struct ifla_vf_link_state { __u32 vf; - __u8 mac[32]; - __u32 vlan; - __u32 qos; - __u32 tx_rate; - __u32 spoofchk; + __u32 link_state; }; -#endif /* VF ports management section * @@ -393,4 +528,37 @@ struct ifla_port_vsi { __u8 pad[3]; }; -#endif /* _LINUX_IF_LINK_H */ + +/* IPoIB section */ + +enum { + IFLA_IPOIB_UNSPEC, + IFLA_IPOIB_PKEY, + IFLA_IPOIB_MODE, + IFLA_IPOIB_UMCAST, + __IFLA_IPOIB_MAX +}; + +enum { + IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ + IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ +}; + +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) + + +/* HSR section */ + +enum { + IFLA_HSR_UNSPEC, + IFLA_HSR_SLAVE1, + IFLA_HSR_SLAVE2, + IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ + IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ + IFLA_HSR_SEQ_NR, + __IFLA_HSR_MAX, +}; + +#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) + +#endif /* _UAPI_LINUX_IF_LINK_H */ -- 1.9.3 From 36365bdd3df389d8f720782708a4735ccb36128c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 25 Jul 2014 14:36:29 -0500 Subject: [PATCH 2/2] link/inet6: add link IPv6 address generation mode support Signed-off-by: Dan Williams Signed-off-by: Thomas Haller (cherry picked from commit 558f966782539f6d975da705fd73cea561c9dc83) Conflicts: include/Makefile.am lib/route/link/inet6.c --- include/Makefile.am | 1 + include/netlink/route/link/inet6.h | 37 +++++++++++++ lib/route/link/inet6.c | 109 ++++++++++++++++++++++++++++++++++--- 3 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 include/netlink/route/link/inet6.h diff --git a/include/Makefile.am b/include/Makefile.am index 1e07fdb..b9487e0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -44,6 +44,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/link/bonding.h \ netlink/route/link/can.h \ netlink/route/link/inet.h \ + netlink/route/link/inet6.h \ netlink/route/link/vlan.h \ netlink/route/qdisc/cbq.h \ netlink/route/qdisc/dsmark.h \ diff --git a/include/netlink/route/link/inet6.h b/include/netlink/route/link/inet6.h new file mode 100644 index 0000000..8ffeab2 --- /dev/null +++ b/include/netlink/route/link/inet6.h @@ -0,0 +1,37 @@ +/* + * netlink/route/link/inet6.h INET6 Link Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2014 Dan Williams + */ + +#ifndef NETLINK_LINK_INET6_H_ +#define NETLINK_LINK_INET6_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +const char * rtnl_link_inet6_addrgenmode2str (uint8_t mode, + char *buf, + size_t len); + +uint8_t rtnl_link_inet6_str2addrgenmode (const char *mode); + +extern int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *, + uint8_t *); + +extern int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *, + uint8_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 6fa2741..e94bf0c 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -15,16 +15,25 @@ #include #include +#define I6_ADDR_GEN_MODE_UNKNOWN UINT8_MAX + struct inet6_data { uint32_t i6_flags; struct ifla_cacheinfo i6_cacheinfo; uint32_t i6_conf[DEVCONF_MAX]; + uint8_t i6_addr_gen_mode; }; static void *inet6_alloc(struct rtnl_link *link) { - return calloc(1, sizeof(struct inet6_data)); + struct inet6_data *i6; + + i6 = calloc(1, sizeof(struct inet6_data)); + if (i6) + i6->i6_addr_gen_mode = I6_ADDR_GEN_MODE_UNKNOWN; + + return i6; } static void *inet6_clone(struct rtnl_link *link, void *data) @@ -43,11 +52,12 @@ static void inet6_free(struct rtnl_link *link, void *data) } static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = { - [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, - [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) }, - [IFLA_INET6_CONF] = { .minlen = 4 }, - [IFLA_INET6_STATS] = { .minlen = 8 }, - [IFLA_INET6_ICMP6STATS] = { .minlen = 8 }, + [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, + [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) }, + [IFLA_INET6_CONF] = { .minlen = 4 }, + [IFLA_INET6_STATS] = { .minlen = 8 }, + [IFLA_INET6_ICMP6STATS] = { .minlen = 8 }, + [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 }, }; static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = { @@ -155,7 +165,10 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, if (tb[IFLA_INET6_CONF]) nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], sizeof(i6->i6_conf)); - + + if (tb[IFLA_INET6_ADDR_GEN_MODE]) + i6->i6_addr_gen_mode = nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]); + /* * Due to 32bit data alignment, these addresses must be copied to an * aligned location prior to access. @@ -200,6 +213,19 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, return 0; } +static int inet6_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data) +{ + struct inet6_data *id = data; + + if (id->i6_addr_gen_mode != I6_ADDR_GEN_MODE_UNKNOWN) + NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, id->i6_addr_gen_mode); + + return 0; + +nla_put_failure: + return -NLE_MSGSIZE; +} + /* These live in include/net/if_inet6.h and should be moved to include/linux */ #define IF_RA_OTHERCONF 0x80 #define IF_RA_MANAGED 0x40 @@ -259,6 +285,22 @@ static char *inet6_devconf2str(int type, char *buf, size_t len) ARRAY_SIZE(inet6_devconf)); } +static const struct trans_tbl inet6_addr_gen_mode[] = { + __ADD(IN6_ADDR_GEN_MODE_EUI64, eui64) + __ADD(IN6_ADDR_GEN_MODE_NONE, none) +}; + +const char *rtnl_link_inet6_addrgenmode2str(uint8_t mode, char *buf, size_t len) +{ + return __type2str(mode, buf, len, inet6_addr_gen_mode, + ARRAY_SIZE(inet6_addr_gen_mode)); +} + +uint8_t rtnl_link_inet6_str2addrgenmode(const char *mode) +{ + return (uint8_t) __str2type(mode, inet6_addr_gen_mode, + ARRAY_SIZE(inet6_addr_gen_mode)); +} static void inet6_dump_details(struct rtnl_link *link, struct nl_dump_params *p, void *data) @@ -281,6 +323,10 @@ static void inet6_dump_details(struct rtnl_link *link, nl_dump(p, " retrans-time %s\n", nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf))); + nl_dump(p, " link-local address mode %s\n", + rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode, + buf, sizeof(buf))); + nl_dump_line(p, " devconf:\n"); nl_dump_line(p, " "); @@ -468,11 +514,60 @@ static struct rtnl_link_af_ops inet6_ops = { .ao_free = &inet6_free, .ao_parse_protinfo = &inet6_parse_protinfo, .ao_parse_af = &inet6_parse_protinfo, + .ao_fill_af = &inet6_fill_af, .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details, .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats, .ao_protinfo_policy = &protinfo_policy, }; +/** + * Get IPv6 link-local address generation mode + * @arg link Link object + * @arg mode Generation mode on success + * + * Returns the link's IPv6 link-local address generation mode. + * + * @return 0 on success + * @return -NLE_NOATTR configuration setting not available + * @return -NLE_INVAL generation mode unknown. If the link was received via + * netlink, it means that address generation mode is not + * supported by the kernel. + */ +int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *link, uint8_t *mode) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + if (id->i6_addr_gen_mode == I6_ADDR_GEN_MODE_UNKNOWN) + return -NLE_INVAL; + + *mode = id->i6_addr_gen_mode; + return 0; +} + +/** + * Set IPv6 link-local address generation mode + * @arg link Link object + * @arg mode Generation mode + * + * Sets the link's IPv6 link-local address generation mode. + * + * @return 0 on success + * @return -NLE_NOMEM could not allocate inet6 data + */ +int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *link, uint8_t mode) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) + return -NLE_NOMEM; + + id->i6_addr_gen_mode = mode; + return 0; +} + static void __init inet6_init(void) { rtnl_link_af_register(&inet6_ops); -- 1.9.3