@@ -47,36 +47,38 @@ enum {
47
47
/* Type structure */
48
48
struct bitmap_ipmac {
49
49
void * members ; /* the set members */
50
- void * extensions ; /* MAC + data extensions */
51
50
u32 first_ip ; /* host byte order, included in range */
52
51
u32 last_ip ; /* host byte order, included in range */
53
52
u32 elements ; /* number of max elements in the set */
54
53
size_t memsize ; /* members size */
55
54
struct timer_list gc ; /* garbage collector */
55
+ unsigned char extensions [0 ] /* MAC + data extensions */
56
+ __aligned (__alignof__ (u64 ));
56
57
};
57
58
58
59
/* ADT structure for generic function args */
59
60
struct bitmap_ipmac_adt_elem {
61
+ unsigned char ether [ETH_ALEN ] __aligned (2 );
60
62
u16 id ;
61
- unsigned char * ether ;
63
+ u16 add_mac ;
62
64
};
63
65
64
66
struct bitmap_ipmac_elem {
65
67
unsigned char ether [ETH_ALEN ];
66
68
unsigned char filled ;
67
- } __attribute__ (( aligned ));
69
+ } __aligned ( __alignof__ ( u64 ));
68
70
69
71
static inline u32
70
72
ip_to_id (const struct bitmap_ipmac * m , u32 ip )
71
73
{
72
74
return ip - m -> first_ip ;
73
75
}
74
76
75
- static inline struct bitmap_ipmac_elem *
76
- get_elem ( void * extensions , u16 id , size_t dsize )
77
- {
78
- return ( struct bitmap_ipmac_elem * )( extensions + id * dsize );
79
- }
77
+ #define get_elem ( extensions , id , dsize ) \
78
+ (struct bitmap_ipmac_elem *)( extensions + (id) * ( dsize) )
79
+
80
+ #define get_const_elem ( extensions , id , dsize ) \
81
+ (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
80
82
81
83
/* Common functions */
82
84
@@ -88,10 +90,9 @@ bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
88
90
89
91
if (!test_bit (e -> id , map -> members ))
90
92
return 0 ;
91
- elem = get_elem (map -> extensions , e -> id , dsize );
92
- if (elem -> filled == MAC_FILLED )
93
- return !e -> ether ||
94
- ether_addr_equal (e -> ether , elem -> ether );
93
+ elem = get_const_elem (map -> extensions , e -> id , dsize );
94
+ if (e -> add_mac && elem -> filled == MAC_FILLED )
95
+ return ether_addr_equal (e -> ether , elem -> ether );
95
96
/* Trigger kernel to fill out the ethernet address */
96
97
return - EAGAIN ;
97
98
}
@@ -103,7 +104,7 @@ bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
103
104
104
105
if (!test_bit (id , map -> members ))
105
106
return 0 ;
106
- elem = get_elem (map -> extensions , id , dsize );
107
+ elem = get_const_elem (map -> extensions , id , dsize );
107
108
/* Timer not started for the incomplete elements */
108
109
return elem -> filled == MAC_FILLED ;
109
110
}
@@ -133,7 +134,7 @@ bitmap_ipmac_add_timeout(unsigned long *timeout,
133
134
* and we can reuse it later when MAC is filled out,
134
135
* possibly by the kernel
135
136
*/
136
- if (e -> ether )
137
+ if (e -> add_mac )
137
138
ip_set_timeout_set (timeout , t );
138
139
else
139
140
* timeout = t ;
@@ -150,7 +151,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
150
151
elem = get_elem (map -> extensions , e -> id , dsize );
151
152
if (test_bit (e -> id , map -> members )) {
152
153
if (elem -> filled == MAC_FILLED ) {
153
- if (e -> ether &&
154
+ if (e -> add_mac &&
154
155
(flags & IPSET_FLAG_EXIST ) &&
155
156
!ether_addr_equal (e -> ether , elem -> ether )) {
156
157
/* memcpy isn't atomic */
@@ -159,7 +160,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
159
160
ether_addr_copy (elem -> ether , e -> ether );
160
161
}
161
162
return IPSET_ADD_FAILED ;
162
- } else if (!e -> ether )
163
+ } else if (!e -> add_mac )
163
164
/* Already added without ethernet address */
164
165
return IPSET_ADD_FAILED ;
165
166
/* Fill the MAC address and trigger the timer activation */
@@ -168,7 +169,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
168
169
ether_addr_copy (elem -> ether , e -> ether );
169
170
elem -> filled = MAC_FILLED ;
170
171
return IPSET_ADD_START_STORED_TIMEOUT ;
171
- } else if (e -> ether ) {
172
+ } else if (e -> add_mac ) {
172
173
/* We can store MAC too */
173
174
ether_addr_copy (elem -> ether , e -> ether );
174
175
elem -> filled = MAC_FILLED ;
@@ -191,7 +192,7 @@ bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
191
192
u32 id , size_t dsize )
192
193
{
193
194
const struct bitmap_ipmac_elem * elem =
194
- get_elem (map -> extensions , id , dsize );
195
+ get_const_elem (map -> extensions , id , dsize );
195
196
196
197
return nla_put_ipaddr4 (skb , IPSET_ATTR_IP ,
197
198
htonl (map -> first_ip + id )) ||
@@ -213,7 +214,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
213
214
{
214
215
struct bitmap_ipmac * map = set -> data ;
215
216
ipset_adtfn adtfn = set -> variant -> adt [adt ];
216
- struct bitmap_ipmac_adt_elem e = { .id = 0 };
217
+ struct bitmap_ipmac_adt_elem e = { .id = 0 , . add_mac = 1 };
217
218
struct ip_set_ext ext = IP_SET_INIT_KEXT (skb , opt , set );
218
219
u32 ip ;
219
220
@@ -231,7 +232,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
231
232
return - EINVAL ;
232
233
233
234
e .id = ip_to_id (map , ip );
234
- e .ether = eth_hdr (skb )-> h_source ;
235
+ memcpy ( e .ether , eth_hdr (skb )-> h_source , ETH_ALEN ) ;
235
236
236
237
return adtfn (set , & e , & ext , & opt -> ext , opt -> cmdflags );
237
238
}
@@ -265,11 +266,10 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
265
266
return - IPSET_ERR_BITMAP_RANGE ;
266
267
267
268
e .id = ip_to_id (map , ip );
268
- if (tb [IPSET_ATTR_ETHER ])
269
- e .ether = nla_data (tb [IPSET_ATTR_ETHER ]);
270
- else
271
- e .ether = NULL ;
272
-
269
+ if (tb [IPSET_ATTR_ETHER ]) {
270
+ memcpy (e .ether , nla_data (tb [IPSET_ATTR_ETHER ]), ETH_ALEN );
271
+ e .add_mac = 1 ;
272
+ }
273
273
ret = adtfn (set , & e , & ext , & ext , flags );
274
274
275
275
return ip_set_eexist (ret , flags ) ? 0 : ret ;
@@ -300,13 +300,6 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
300
300
map -> members = ip_set_alloc (map -> memsize );
301
301
if (!map -> members )
302
302
return false;
303
- if (set -> dsize ) {
304
- map -> extensions = ip_set_alloc (set -> dsize * elements );
305
- if (!map -> extensions ) {
306
- kfree (map -> members );
307
- return false;
308
- }
309
- }
310
303
map -> first_ip = first_ip ;
311
304
map -> last_ip = last_ip ;
312
305
map -> elements = elements ;
@@ -361,14 +354,15 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
361
354
if (elements > IPSET_BITMAP_MAX_RANGE + 1 )
362
355
return - IPSET_ERR_BITMAP_RANGE_SIZE ;
363
356
364
- map = kzalloc (sizeof (* map ), GFP_KERNEL );
357
+ set -> dsize = ip_set_elem_len (set , tb ,
358
+ sizeof (struct bitmap_ipmac_elem ),
359
+ __alignof__(struct bitmap_ipmac_elem ));
360
+ map = ip_set_alloc (sizeof (* map ) + elements * set -> dsize );
365
361
if (!map )
366
362
return - ENOMEM ;
367
363
368
364
map -> memsize = bitmap_bytes (0 , elements - 1 );
369
365
set -> variant = & bitmap_ipmac ;
370
- set -> dsize = ip_set_elem_len (set , tb ,
371
- sizeof (struct bitmap_ipmac_elem ));
372
366
if (!init_map_ipmac (set , map , first_ip , last_ip , elements )) {
373
367
kfree (map );
374
368
return - ENOMEM ;
0 commit comments