2005-04-16 15:20:36 -07:00
# ifndef __BEN_VLAN_802_1Q_INC__
# define __BEN_VLAN_802_1Q_INC__
# include <linux/if_vlan.h>
2010-06-24 00:55:06 +00:00
# include <linux/u64_stats_sync.h>
2011-12-08 04:11:18 +00:00
# include <linux/list.h>
2005-04-16 15:20:36 -07:00
2011-12-08 04:11:18 +00:00
/* if this changes, algorithm will have to be reworked because this
* depends on completely exhausting the VLAN identifier space . Thus
* it gives constant time look - up , but in many cases it wastes memory .
*/
# define VLAN_GROUP_ARRAY_SPLIT_PARTS 8
# define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID / VLAN_GROUP_ARRAY_SPLIT_PARTS)
2013-04-19 02:04:29 +00:00
enum vlan_protos {
VLAN_PROTO_8021Q = 0 ,
net: vlan: add 802.1ad support
Add support for 802.1ad VLAN devices. This mainly consists of checking for
ETH_P_8021AD in addition to ETH_P_8021Q in a couple of places and check
offloading capabilities based on the used protocol.
Configuration is done using "ip link":
# ip link add link eth0 eth0.1000 \
type vlan proto 802.1ad id 1000
# ip link add link eth0.1000 eth0.1000.1000 \
type vlan proto 802.1q id 1000
52:54:00:12:34:56 > 92:b1:54:28:e4:8c, ethertype 802.1Q (0x8100), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
20.1.0.2 > 20.1.0.1: ICMP echo request, id 3003, seq 8, length 64
92:b1:54:28:e4:8c > 52:54:00:12:34:56, ethertype 802.1Q-QinQ (0x88a8), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 47944, offset 0, flags [none], proto ICMP (1), length 84)
20.1.0.1 > 20.1.0.2: ICMP echo reply, id 3003, seq 8, length 64
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-04-19 02:04:31 +00:00
VLAN_PROTO_8021AD ,
2013-04-19 02:04:29 +00:00
VLAN_PROTO_NUM ,
} ;
2011-12-08 04:11:18 +00:00
struct vlan_group {
unsigned int nr_vlan_devs ;
struct hlist_node hlist ; /* linked list */
2013-04-19 02:04:29 +00:00
struct net_device * * vlan_devices_arrays [ VLAN_PROTO_NUM ]
[ VLAN_GROUP_ARRAY_SPLIT_PARTS ] ;
2011-12-08 04:11:18 +00:00
} ;
struct vlan_info {
struct net_device * real_dev ; /* The ethernet(like) device
* the vlan is attached to .
*/
struct vlan_group grp ;
struct list_head vid_list ;
unsigned int nr_vids ;
struct rcu_head rcu ;
} ;
2013-04-19 02:04:29 +00:00
static inline unsigned int vlan_proto_idx ( __be16 proto )
{
switch ( proto ) {
2014-03-12 10:04:15 -07:00
case htons ( ETH_P_8021Q ) :
2013-04-19 02:04:29 +00:00
return VLAN_PROTO_8021Q ;
2014-03-12 10:04:15 -07:00
case htons ( ETH_P_8021AD ) :
net: vlan: add 802.1ad support
Add support for 802.1ad VLAN devices. This mainly consists of checking for
ETH_P_8021AD in addition to ETH_P_8021Q in a couple of places and check
offloading capabilities based on the used protocol.
Configuration is done using "ip link":
# ip link add link eth0 eth0.1000 \
type vlan proto 802.1ad id 1000
# ip link add link eth0.1000 eth0.1000.1000 \
type vlan proto 802.1q id 1000
52:54:00:12:34:56 > 92:b1:54:28:e4:8c, ethertype 802.1Q (0x8100), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
20.1.0.2 > 20.1.0.1: ICMP echo request, id 3003, seq 8, length 64
92:b1:54:28:e4:8c > 52:54:00:12:34:56, ethertype 802.1Q-QinQ (0x88a8), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 47944, offset 0, flags [none], proto ICMP (1), length 84)
20.1.0.1 > 20.1.0.2: ICMP echo reply, id 3003, seq 8, length 64
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-04-19 02:04:31 +00:00
return VLAN_PROTO_8021AD ;
2013-04-19 02:04:29 +00:00
default :
BUG ( ) ;
2013-04-21 00:09:32 +00:00
return 0 ;
2013-04-19 02:04:29 +00:00
}
}
static inline struct net_device * __vlan_group_get_device ( struct vlan_group * vg ,
unsigned int pidx ,
u16 vlan_id )
2011-07-20 04:54:49 +00:00
{
struct net_device * * array ;
2013-04-19 02:04:29 +00:00
array = vg - > vlan_devices_arrays [ pidx ]
[ vlan_id / VLAN_GROUP_ARRAY_PART_LEN ] ;
2011-07-20 04:54:49 +00:00
return array ? array [ vlan_id % VLAN_GROUP_ARRAY_PART_LEN ] : NULL ;
}
2013-04-19 02:04:29 +00:00
static inline struct net_device * vlan_group_get_device ( struct vlan_group * vg ,
__be16 vlan_proto ,
u16 vlan_id )
{
return __vlan_group_get_device ( vg , vlan_proto_idx ( vlan_proto ) , vlan_id ) ;
}
2011-07-20 04:54:49 +00:00
static inline void vlan_group_set_device ( struct vlan_group * vg ,
2013-04-19 02:04:29 +00:00
__be16 vlan_proto , u16 vlan_id ,
2011-07-20 04:54:49 +00:00
struct net_device * dev )
{
struct net_device * * array ;
if ( ! vg )
return ;
2013-04-19 02:04:29 +00:00
array = vg - > vlan_devices_arrays [ vlan_proto_idx ( vlan_proto ) ]
[ vlan_id / VLAN_GROUP_ARRAY_PART_LEN ] ;
2011-07-20 04:54:49 +00:00
array [ vlan_id % VLAN_GROUP_ARRAY_PART_LEN ] = dev ;
}
2011-07-17 08:53:12 +00:00
/* Must be invoked with rcu_read_lock or with RTNL. */
static inline struct net_device * vlan_find_dev ( struct net_device * real_dev ,
2013-04-19 02:04:29 +00:00
__be16 vlan_proto , u16 vlan_id )
2011-07-17 08:53:12 +00:00
{
2011-12-08 04:11:18 +00:00
struct vlan_info * vlan_info = rcu_dereference_rtnl ( real_dev - > vlan_info ) ;
2011-07-17 08:53:12 +00:00
2011-12-08 04:11:18 +00:00
if ( vlan_info )
2013-04-19 02:04:29 +00:00
return vlan_group_get_device ( & vlan_info - > grp ,
vlan_proto , vlan_id ) ;
2011-07-17 08:53:12 +00:00
return NULL ;
}
2013-04-19 02:04:29 +00:00
# define vlan_group_for_each_dev(grp, i, dev) \
for ( ( i ) = 0 ; i < VLAN_PROTO_NUM * VLAN_N_VID ; i + + ) \
if ( ( ( dev ) = __vlan_group_get_device ( ( grp ) , ( i ) / VLAN_N_VID , \
( i ) % VLAN_N_VID ) ) )
2005-04-16 15:20:36 -07:00
/* found in vlan_dev.c */
2007-06-13 12:05:22 -07:00
void vlan_dev_set_ingress_priority ( const struct net_device * dev ,
2008-07-08 03:24:44 -07:00
u32 skb_prio , u16 vlan_prio ) ;
2007-06-13 12:05:22 -07:00
int vlan_dev_set_egress_priority ( const struct net_device * dev ,
2008-07-08 03:24:44 -07:00
u32 skb_prio , u16 vlan_prio ) ;
2008-07-05 21:26:27 -07:00
int vlan_dev_change_flags ( const struct net_device * dev , u32 flag , u32 mask ) ;
2007-06-13 12:05:22 -07:00
void vlan_dev_get_realdev_name ( const struct net_device * dev , char * result ) ;
2005-04-16 15:20:36 -07:00
2013-04-19 02:04:29 +00:00
int vlan_check_real_dev ( struct net_device * real_dev ,
__be16 protocol , u16 vlan_id ) ;
2007-06-13 12:07:54 -07:00
void vlan_setup ( struct net_device * dev ) ;
2017-10-04 17:48:47 -07:00
int register_vlan_dev ( struct net_device * dev , struct netlink_ext_ack * extack ) ;
2009-10-27 07:06:36 +00:00
void unregister_vlan_dev ( struct net_device * dev , struct list_head * head ) ;
2016-05-27 17:45:07 +01:00
bool vlan_dev_inherit_address ( struct net_device * dev ,
struct net_device * real_dev ) ;
2007-06-13 12:07:54 -07:00
2008-07-08 03:23:36 -07:00
static inline u32 vlan_get_ingress_priority ( struct net_device * dev ,
2008-07-08 03:24:44 -07:00
u16 vlan_tci )
2008-07-08 03:23:36 -07:00
{
2011-12-08 04:11:15 +00:00
struct vlan_dev_priv * vip = vlan_dev_priv ( dev ) ;
2008-07-08 03:23:36 -07:00
2009-10-26 18:40:35 -07:00
return vip - > ingress_priority_map [ ( vlan_tci > > VLAN_PRIO_SHIFT ) & 0x7 ] ;
2008-07-08 03:23:36 -07:00
}
2008-07-05 21:26:57 -07:00
# ifdef CONFIG_VLAN_8021Q_GVRP
2013-10-18 13:48:22 -07:00
int vlan_gvrp_request_join ( const struct net_device * dev ) ;
void vlan_gvrp_request_leave ( const struct net_device * dev ) ;
int vlan_gvrp_init_applicant ( struct net_device * dev ) ;
void vlan_gvrp_uninit_applicant ( struct net_device * dev ) ;
int vlan_gvrp_init ( void ) ;
void vlan_gvrp_uninit ( void ) ;
2008-07-05 21:26:57 -07:00
# else
static inline int vlan_gvrp_request_join ( const struct net_device * dev ) { return 0 ; }
static inline void vlan_gvrp_request_leave ( const struct net_device * dev ) { }
static inline int vlan_gvrp_init_applicant ( struct net_device * dev ) { return 0 ; }
static inline void vlan_gvrp_uninit_applicant ( struct net_device * dev ) { }
static inline int vlan_gvrp_init ( void ) { return 0 ; }
static inline void vlan_gvrp_uninit ( void ) { }
# endif
2013-02-08 17:17:07 +00:00
# ifdef CONFIG_VLAN_8021Q_MVRP
2013-10-18 13:48:22 -07:00
int vlan_mvrp_request_join ( const struct net_device * dev ) ;
void vlan_mvrp_request_leave ( const struct net_device * dev ) ;
int vlan_mvrp_init_applicant ( struct net_device * dev ) ;
void vlan_mvrp_uninit_applicant ( struct net_device * dev ) ;
int vlan_mvrp_init ( void ) ;
void vlan_mvrp_uninit ( void ) ;
2013-02-08 17:17:07 +00:00
# else
static inline int vlan_mvrp_request_join ( const struct net_device * dev ) { return 0 ; }
static inline void vlan_mvrp_request_leave ( const struct net_device * dev ) { }
static inline int vlan_mvrp_init_applicant ( struct net_device * dev ) { return 0 ; }
static inline void vlan_mvrp_uninit_applicant ( struct net_device * dev ) { }
static inline int vlan_mvrp_init ( void ) { return 0 ; }
static inline void vlan_mvrp_uninit ( void ) { }
# endif
2008-10-28 22:12:36 -07:00
extern const char vlan_fullname [ ] ;
extern const char vlan_version [ ] ;
2013-10-18 13:48:22 -07:00
int vlan_netlink_init ( void ) ;
void vlan_netlink_fini ( void ) ;
2007-06-13 12:07:54 -07:00
extern struct rtnl_link_ops vlan_link_ops ;
netns: make struct pernet_operations::id unsigned int
Make struct pernet_operations::id unsigned.
There are 2 reasons to do so:
1)
This field is really an index into an zero based array and
thus is unsigned entity. Using negative value is out-of-bound
access by definition.
2)
On x86_64 unsigned 32-bit data which are mixed with pointers
via array indexing or offsets added or subtracted to pointers
are preffered to signed 32-bit data.
"int" being used as an array index needs to be sign-extended
to 64-bit before being used.
void f(long *p, int i)
{
g(p[i]);
}
roughly translates to
movsx rsi, esi
mov rdi, [rsi+...]
call g
MOVSX is 3 byte instruction which isn't necessary if the variable is
unsigned because x86_64 is zero extending by default.
Now, there is net_generic() function which, you guessed it right, uses
"int" as an array index:
static inline void *net_generic(const struct net *net, int id)
{
...
ptr = ng->ptr[id - 1];
...
}
And this function is used a lot, so those sign extensions add up.
Patch snipes ~1730 bytes on allyesconfig kernel (without all junk
messing with code generation):
add/remove: 0/0 grow/shrink: 70/598 up/down: 396/-2126 (-1730)
Unfortunately some functions actually grow bigger.
This is a semmingly random artefact of code generation with register
allocator being used differently. gcc decides that some variable
needs to live in new r8+ registers and every access now requires REX
prefix. Or it is shifted into r12, so [r12+0] addressing mode has to be
used which is longer than [r8]
However, overall balance is in negative direction:
add/remove: 0/0 grow/shrink: 70/598 up/down: 396/-2126 (-1730)
function old new delta
nfsd4_lock 3886 3959 +73
tipc_link_build_proto_msg 1096 1140 +44
mac80211_hwsim_new_radio 2776 2808 +32
tipc_mon_rcv 1032 1058 +26
svcauth_gss_legacy_init 1413 1429 +16
tipc_bcbase_select_primary 379 392 +13
nfsd4_exchange_id 1247 1260 +13
nfsd4_setclientid_confirm 782 793 +11
...
put_client_renew_locked 494 480 -14
ip_set_sockfn_get 730 716 -14
geneve_sock_add 829 813 -16
nfsd4_sequence_done 721 703 -18
nlmclnt_lookup_host 708 686 -22
nfsd4_lockt 1085 1063 -22
nfs_get_client 1077 1050 -27
tcf_bpf_init 1106 1076 -30
nfsd4_encode_fattr 5997 5930 -67
Total: Before=154856051, After=154854321, chg -0.00%
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-11-17 04:58:21 +03:00
extern unsigned int vlan_net_id ;
2008-04-16 00:49:09 -07:00
2008-04-16 00:51:51 -07:00
struct proc_dir_entry ;
2008-04-16 00:49:09 -07:00
struct vlan_net {
2008-04-16 00:51:51 -07:00
/* /proc/net/vlan */
struct proc_dir_entry * proc_vlan_dir ;
/* /proc/net/vlan/config */
struct proc_dir_entry * proc_vlan_conf ;
2008-04-16 00:54:39 -07:00
/* Determines interface naming scheme. */
unsigned short name_type ;
2008-04-16 00:49:09 -07:00
} ;
2005-04-16 15:20:36 -07:00
# endif /* !(__BEN_VLAN_802_1Q_INC__) */