2 * IEEE 802.1Q Multiple Registration Protocol (MRP)
4 * Copyright (c) 2012 Massachusetts Institute of Technology
6 * Adapted from code in net/802/garp.c
7 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
13 #include <linux/kernel.h>
14 #include <linux/timer.h>
15 #include <linux/skbuff.h>
16 #include <linux/netdevice.h>
17 #include <linux/etherdevice.h>
18 #include <linux/rtnetlink.h>
19 #include <linux/slab.h>
20 #include <linux/module.h>
22 #include <asm/unaligned.h>
24 static unsigned int mrp_join_time __read_mostly
= 200;
25 module_param(mrp_join_time
, uint
, 0644);
26 MODULE_PARM_DESC(mrp_join_time
, "Join time in ms (default 200ms)");
28 static unsigned int mrp_periodic_time __read_mostly
= 1000;
29 module_param(mrp_periodic_time
, uint
, 0644);
30 MODULE_PARM_DESC(mrp_periodic_time
, "Periodic time in ms (default 1s)");
32 MODULE_LICENSE("GPL");
35 mrp_applicant_state_table
[MRP_APPLICANT_MAX
+ 1][MRP_EVENT_MAX
+ 1] = {
36 [MRP_APPLICANT_VO
] = {
37 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
38 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VP
,
39 [MRP_EVENT_LV
] = MRP_APPLICANT_VO
,
40 [MRP_EVENT_TX
] = MRP_APPLICANT_VO
,
41 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VO
,
42 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AO
,
43 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VO
,
44 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VO
,
45 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VO
,
46 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
47 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
48 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
49 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VO
,
51 [MRP_APPLICANT_VP
] = {
52 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
53 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VP
,
54 [MRP_EVENT_LV
] = MRP_APPLICANT_VO
,
55 [MRP_EVENT_TX
] = MRP_APPLICANT_AA
,
56 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VP
,
57 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AP
,
58 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VP
,
59 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VP
,
60 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VP
,
61 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
62 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
63 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
64 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VP
,
66 [MRP_APPLICANT_VN
] = {
67 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
68 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VN
,
69 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
70 [MRP_EVENT_TX
] = MRP_APPLICANT_AN
,
71 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VN
,
72 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_VN
,
73 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VN
,
74 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VN
,
75 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VN
,
76 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VN
,
77 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VN
,
78 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VN
,
79 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VN
,
81 [MRP_APPLICANT_AN
] = {
82 [MRP_EVENT_NEW
] = MRP_APPLICANT_AN
,
83 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AN
,
84 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
85 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
86 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AN
,
87 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AN
,
88 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AN
,
89 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AN
,
90 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AN
,
91 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VN
,
92 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VN
,
93 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VN
,
94 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AN
,
96 [MRP_APPLICANT_AA
] = {
97 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
98 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AA
,
99 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
100 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
101 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AA
,
102 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QA
,
103 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AA
,
104 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AA
,
105 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AA
,
106 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
107 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
108 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
109 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AA
,
111 [MRP_APPLICANT_QA
] = {
112 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
113 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QA
,
114 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
115 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
116 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QA
,
117 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QA
,
118 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QA
,
119 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AA
,
120 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AA
,
121 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
122 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
123 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
124 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AA
,
126 [MRP_APPLICANT_LA
] = {
127 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
128 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AA
,
129 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
130 [MRP_EVENT_TX
] = MRP_APPLICANT_VO
,
131 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_LA
,
132 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_LA
,
133 [MRP_EVENT_R_IN
] = MRP_APPLICANT_LA
,
134 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_LA
,
135 [MRP_EVENT_R_MT
] = MRP_APPLICANT_LA
,
136 [MRP_EVENT_R_LV
] = MRP_APPLICANT_LA
,
137 [MRP_EVENT_R_LA
] = MRP_APPLICANT_LA
,
138 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_LA
,
139 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_LA
,
141 [MRP_APPLICANT_AO
] = {
142 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
143 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AP
,
144 [MRP_EVENT_LV
] = MRP_APPLICANT_AO
,
145 [MRP_EVENT_TX
] = MRP_APPLICANT_AO
,
146 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AO
,
147 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QO
,
148 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AO
,
149 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AO
,
150 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AO
,
151 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
152 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
153 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
154 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AO
,
156 [MRP_APPLICANT_QO
] = {
157 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
158 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QP
,
159 [MRP_EVENT_LV
] = MRP_APPLICANT_QO
,
160 [MRP_EVENT_TX
] = MRP_APPLICANT_QO
,
161 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QO
,
162 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QO
,
163 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QO
,
164 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AO
,
165 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AO
,
166 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
167 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
168 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
169 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_QO
,
171 [MRP_APPLICANT_AP
] = {
172 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
173 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AP
,
174 [MRP_EVENT_LV
] = MRP_APPLICANT_AO
,
175 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
176 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AP
,
177 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QP
,
178 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AP
,
179 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AP
,
180 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AP
,
181 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
182 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
183 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
184 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AP
,
186 [MRP_APPLICANT_QP
] = {
187 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
188 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QP
,
189 [MRP_EVENT_LV
] = MRP_APPLICANT_QO
,
190 [MRP_EVENT_TX
] = MRP_APPLICANT_QP
,
191 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QP
,
192 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QP
,
193 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QP
,
194 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AP
,
195 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AP
,
196 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
197 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
198 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
199 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AP
,
204 mrp_tx_action_table
[MRP_APPLICANT_MAX
+ 1] = {
205 [MRP_APPLICANT_VO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
206 [MRP_APPLICANT_VP
] = MRP_TX_ACTION_S_JOIN_IN
,
207 [MRP_APPLICANT_VN
] = MRP_TX_ACTION_S_NEW
,
208 [MRP_APPLICANT_AN
] = MRP_TX_ACTION_S_NEW
,
209 [MRP_APPLICANT_AA
] = MRP_TX_ACTION_S_JOIN_IN
,
210 [MRP_APPLICANT_QA
] = MRP_TX_ACTION_S_JOIN_IN_OPTIONAL
,
211 [MRP_APPLICANT_LA
] = MRP_TX_ACTION_S_LV
,
212 [MRP_APPLICANT_AO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
213 [MRP_APPLICANT_QO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
214 [MRP_APPLICANT_AP
] = MRP_TX_ACTION_S_JOIN_IN
,
215 [MRP_APPLICANT_QP
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
218 static void mrp_attrvalue_inc(void *value
, u8 len
)
222 /* Add 1 to the last byte. If it becomes zero,
223 * go to the previous byte and repeat.
225 while (len
> 0 && !++v
[--len
])
229 static int mrp_attr_cmp(const struct mrp_attr
*attr
,
230 const void *value
, u8 len
, u8 type
)
232 if (attr
->type
!= type
)
233 return attr
->type
- type
;
234 if (attr
->len
!= len
)
235 return attr
->len
- len
;
236 return memcmp(attr
->value
, value
, len
);
239 static struct mrp_attr
*mrp_attr_lookup(const struct mrp_applicant
*app
,
240 const void *value
, u8 len
, u8 type
)
242 struct rb_node
*parent
= app
->mad
.rb_node
;
243 struct mrp_attr
*attr
;
247 attr
= rb_entry(parent
, struct mrp_attr
, node
);
248 d
= mrp_attr_cmp(attr
, value
, len
, type
);
250 parent
= parent
->rb_left
;
252 parent
= parent
->rb_right
;
259 static struct mrp_attr
*mrp_attr_create(struct mrp_applicant
*app
,
260 const void *value
, u8 len
, u8 type
)
262 struct rb_node
*parent
= NULL
, **p
= &app
->mad
.rb_node
;
263 struct mrp_attr
*attr
;
268 attr
= rb_entry(parent
, struct mrp_attr
, node
);
269 d
= mrp_attr_cmp(attr
, value
, len
, type
);
271 p
= &parent
->rb_left
;
273 p
= &parent
->rb_right
;
275 /* The attribute already exists; re-use it. */
279 attr
= kmalloc(sizeof(*attr
) + len
, GFP_ATOMIC
);
282 attr
->state
= MRP_APPLICANT_VO
;
285 memcpy(attr
->value
, value
, len
);
287 rb_link_node(&attr
->node
, parent
, p
);
288 rb_insert_color(&attr
->node
, &app
->mad
);
292 static void mrp_attr_destroy(struct mrp_applicant
*app
, struct mrp_attr
*attr
)
294 rb_erase(&attr
->node
, &app
->mad
);
298 static int mrp_pdu_init(struct mrp_applicant
*app
)
301 struct mrp_pdu_hdr
*ph
;
303 skb
= alloc_skb(app
->dev
->mtu
+ LL_RESERVED_SPACE(app
->dev
),
309 skb
->protocol
= app
->app
->pkttype
.type
;
310 skb_reserve(skb
, LL_RESERVED_SPACE(app
->dev
));
311 skb_reset_network_header(skb
);
312 skb_reset_transport_header(skb
);
314 ph
= __skb_put(skb
, sizeof(*ph
));
315 ph
->version
= app
->app
->version
;
321 static int mrp_pdu_append_end_mark(struct mrp_applicant
*app
)
325 if (skb_tailroom(app
->pdu
) < sizeof(*endmark
))
327 endmark
= __skb_put(app
->pdu
, sizeof(*endmark
));
328 put_unaligned(MRP_END_MARK
, endmark
);
332 static void mrp_pdu_queue(struct mrp_applicant
*app
)
337 if (mrp_cb(app
->pdu
)->mh
)
338 mrp_pdu_append_end_mark(app
);
339 mrp_pdu_append_end_mark(app
);
341 dev_hard_header(app
->pdu
, app
->dev
, ntohs(app
->app
->pkttype
.type
),
342 app
->app
->group_address
, app
->dev
->dev_addr
,
345 skb_queue_tail(&app
->queue
, app
->pdu
);
349 static void mrp_queue_xmit(struct mrp_applicant
*app
)
353 while ((skb
= skb_dequeue(&app
->queue
)))
357 static int mrp_pdu_append_msg_hdr(struct mrp_applicant
*app
,
358 u8 attrtype
, u8 attrlen
)
360 struct mrp_msg_hdr
*mh
;
362 if (mrp_cb(app
->pdu
)->mh
) {
363 if (mrp_pdu_append_end_mark(app
) < 0)
365 mrp_cb(app
->pdu
)->mh
= NULL
;
366 mrp_cb(app
->pdu
)->vah
= NULL
;
369 if (skb_tailroom(app
->pdu
) < sizeof(*mh
))
371 mh
= __skb_put(app
->pdu
, sizeof(*mh
));
372 mh
->attrtype
= attrtype
;
373 mh
->attrlen
= attrlen
;
374 mrp_cb(app
->pdu
)->mh
= mh
;
378 static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant
*app
,
379 const void *firstattrvalue
, u8 attrlen
)
381 struct mrp_vecattr_hdr
*vah
;
383 if (skb_tailroom(app
->pdu
) < sizeof(*vah
) + attrlen
)
385 vah
= __skb_put(app
->pdu
, sizeof(*vah
) + attrlen
);
386 put_unaligned(0, &vah
->lenflags
);
387 memcpy(vah
->firstattrvalue
, firstattrvalue
, attrlen
);
388 mrp_cb(app
->pdu
)->vah
= vah
;
389 memcpy(mrp_cb(app
->pdu
)->attrvalue
, firstattrvalue
, attrlen
);
393 static int mrp_pdu_append_vecattr_event(struct mrp_applicant
*app
,
394 const struct mrp_attr
*attr
,
395 enum mrp_vecattr_event vaevent
)
402 err
= mrp_pdu_init(app
);
407 /* If there is no Message header in the PDU, or the Message header is
408 * for a different attribute type, add an EndMark (if necessary) and a
409 * new Message header to the PDU.
411 if (!mrp_cb(app
->pdu
)->mh
||
412 mrp_cb(app
->pdu
)->mh
->attrtype
!= attr
->type
||
413 mrp_cb(app
->pdu
)->mh
->attrlen
!= attr
->len
) {
414 if (mrp_pdu_append_msg_hdr(app
, attr
->type
, attr
->len
) < 0)
418 /* If there is no VectorAttribute header for this Message in the PDU,
419 * or this attribute's value does not sequentially follow the previous
420 * attribute's value, add a new VectorAttribute header to the PDU.
422 if (!mrp_cb(app
->pdu
)->vah
||
423 memcmp(mrp_cb(app
->pdu
)->attrvalue
, attr
->value
, attr
->len
)) {
424 if (mrp_pdu_append_vecattr_hdr(app
, attr
->value
, attr
->len
) < 0)
428 len
= be16_to_cpu(get_unaligned(&mrp_cb(app
->pdu
)->vah
->lenflags
));
431 /* Events are packed into Vectors in the PDU, three to a byte. Add a
432 * byte to the end of the Vector if necessary.
435 if (skb_tailroom(app
->pdu
) < sizeof(u8
))
437 vaevents
= __skb_put(app
->pdu
, sizeof(u8
));
439 vaevents
= (u8
*)(skb_tail_pointer(app
->pdu
) - sizeof(u8
));
444 *vaevents
= vaevent
* (__MRP_VECATTR_EVENT_MAX
*
445 __MRP_VECATTR_EVENT_MAX
);
448 *vaevents
+= vaevent
* __MRP_VECATTR_EVENT_MAX
;
451 *vaevents
+= vaevent
;
457 /* Increment the length of the VectorAttribute in the PDU, as well as
458 * the value of the next attribute that would continue its Vector.
460 put_unaligned(cpu_to_be16(++len
), &mrp_cb(app
->pdu
)->vah
->lenflags
);
461 mrp_attrvalue_inc(mrp_cb(app
->pdu
)->attrvalue
, attr
->len
);
470 static void mrp_attr_event(struct mrp_applicant
*app
,
471 struct mrp_attr
*attr
, enum mrp_event event
)
473 enum mrp_applicant_state state
;
475 state
= mrp_applicant_state_table
[attr
->state
][event
];
476 if (state
== MRP_APPLICANT_INVALID
) {
481 if (event
== MRP_EVENT_TX
) {
482 /* When appending the attribute fails, don't update its state
483 * in order to retry at the next TX event.
486 switch (mrp_tx_action_table
[attr
->state
]) {
487 case MRP_TX_ACTION_NONE
:
488 case MRP_TX_ACTION_S_JOIN_IN_OPTIONAL
:
489 case MRP_TX_ACTION_S_IN_OPTIONAL
:
491 case MRP_TX_ACTION_S_NEW
:
492 if (mrp_pdu_append_vecattr_event(
493 app
, attr
, MRP_VECATTR_EVENT_NEW
) < 0)
496 case MRP_TX_ACTION_S_JOIN_IN
:
497 if (mrp_pdu_append_vecattr_event(
498 app
, attr
, MRP_VECATTR_EVENT_JOIN_IN
) < 0)
501 case MRP_TX_ACTION_S_LV
:
502 if (mrp_pdu_append_vecattr_event(
503 app
, attr
, MRP_VECATTR_EVENT_LV
) < 0)
505 /* As a pure applicant, sending a leave message
506 * implies that the attribute was unregistered and
509 mrp_attr_destroy(app
, attr
);
519 int mrp_request_join(const struct net_device
*dev
,
520 const struct mrp_application
*appl
,
521 const void *value
, u8 len
, u8 type
)
523 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
524 struct mrp_applicant
*app
= rtnl_dereference(
525 port
->applicants
[appl
->type
]);
526 struct mrp_attr
*attr
;
528 if (sizeof(struct mrp_skb_cb
) + len
>
529 FIELD_SIZEOF(struct sk_buff
, cb
))
532 spin_lock_bh(&app
->lock
);
533 attr
= mrp_attr_create(app
, value
, len
, type
);
535 spin_unlock_bh(&app
->lock
);
538 mrp_attr_event(app
, attr
, MRP_EVENT_JOIN
);
539 spin_unlock_bh(&app
->lock
);
542 EXPORT_SYMBOL_GPL(mrp_request_join
);
544 void mrp_request_leave(const struct net_device
*dev
,
545 const struct mrp_application
*appl
,
546 const void *value
, u8 len
, u8 type
)
548 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
549 struct mrp_applicant
*app
= rtnl_dereference(
550 port
->applicants
[appl
->type
]);
551 struct mrp_attr
*attr
;
553 if (sizeof(struct mrp_skb_cb
) + len
>
554 FIELD_SIZEOF(struct sk_buff
, cb
))
557 spin_lock_bh(&app
->lock
);
558 attr
= mrp_attr_lookup(app
, value
, len
, type
);
560 spin_unlock_bh(&app
->lock
);
563 mrp_attr_event(app
, attr
, MRP_EVENT_LV
);
564 spin_unlock_bh(&app
->lock
);
566 EXPORT_SYMBOL_GPL(mrp_request_leave
);
568 static void mrp_mad_event(struct mrp_applicant
*app
, enum mrp_event event
)
570 struct rb_node
*node
, *next
;
571 struct mrp_attr
*attr
;
573 for (node
= rb_first(&app
->mad
);
574 next
= node
? rb_next(node
) : NULL
, node
!= NULL
;
576 attr
= rb_entry(node
, struct mrp_attr
, node
);
577 mrp_attr_event(app
, attr
, event
);
581 static void mrp_join_timer_arm(struct mrp_applicant
*app
)
585 delay
= (u64
)msecs_to_jiffies(mrp_join_time
) * prandom_u32() >> 32;
586 mod_timer(&app
->join_timer
, jiffies
+ delay
);
589 static void mrp_join_timer(struct timer_list
*t
)
591 struct mrp_applicant
*app
= from_timer(app
, t
, join_timer
);
593 spin_lock(&app
->lock
);
594 mrp_mad_event(app
, MRP_EVENT_TX
);
596 spin_unlock(&app
->lock
);
599 mrp_join_timer_arm(app
);
602 static void mrp_periodic_timer_arm(struct mrp_applicant
*app
)
604 mod_timer(&app
->periodic_timer
,
605 jiffies
+ msecs_to_jiffies(mrp_periodic_time
));
608 static void mrp_periodic_timer(struct timer_list
*t
)
610 struct mrp_applicant
*app
= from_timer(app
, t
, periodic_timer
);
612 spin_lock(&app
->lock
);
613 mrp_mad_event(app
, MRP_EVENT_PERIODIC
);
615 spin_unlock(&app
->lock
);
617 mrp_periodic_timer_arm(app
);
620 static int mrp_pdu_parse_end_mark(struct sk_buff
*skb
, int *offset
)
624 if (skb_copy_bits(skb
, *offset
, &endmark
, sizeof(endmark
)) < 0)
626 if (endmark
== MRP_END_MARK
) {
627 *offset
+= sizeof(endmark
);
633 static void mrp_pdu_parse_vecattr_event(struct mrp_applicant
*app
,
635 enum mrp_vecattr_event vaevent
)
637 struct mrp_attr
*attr
;
638 enum mrp_event event
;
640 attr
= mrp_attr_lookup(app
, mrp_cb(skb
)->attrvalue
,
641 mrp_cb(skb
)->mh
->attrlen
,
642 mrp_cb(skb
)->mh
->attrtype
);
647 case MRP_VECATTR_EVENT_NEW
:
648 event
= MRP_EVENT_R_NEW
;
650 case MRP_VECATTR_EVENT_JOIN_IN
:
651 event
= MRP_EVENT_R_JOIN_IN
;
653 case MRP_VECATTR_EVENT_IN
:
654 event
= MRP_EVENT_R_IN
;
656 case MRP_VECATTR_EVENT_JOIN_MT
:
657 event
= MRP_EVENT_R_JOIN_MT
;
659 case MRP_VECATTR_EVENT_MT
:
660 event
= MRP_EVENT_R_MT
;
662 case MRP_VECATTR_EVENT_LV
:
663 event
= MRP_EVENT_R_LV
;
669 mrp_attr_event(app
, attr
, event
);
672 static int mrp_pdu_parse_vecattr(struct mrp_applicant
*app
,
673 struct sk_buff
*skb
, int *offset
)
675 struct mrp_vecattr_hdr _vah
;
677 u8 vaevents
, vaevent
;
679 mrp_cb(skb
)->vah
= skb_header_pointer(skb
, *offset
, sizeof(_vah
),
681 if (!mrp_cb(skb
)->vah
)
683 *offset
+= sizeof(_vah
);
685 if (get_unaligned(&mrp_cb(skb
)->vah
->lenflags
) &
686 MRP_VECATTR_HDR_FLAG_LA
)
687 mrp_mad_event(app
, MRP_EVENT_R_LA
);
688 valen
= be16_to_cpu(get_unaligned(&mrp_cb(skb
)->vah
->lenflags
) &
689 MRP_VECATTR_HDR_LEN_MASK
);
691 /* The VectorAttribute structure in a PDU carries event information
692 * about one or more attributes having consecutive values. Only the
693 * value for the first attribute is contained in the structure. So
694 * we make a copy of that value, and then increment it each time we
695 * advance to the next event in its Vector.
697 if (sizeof(struct mrp_skb_cb
) + mrp_cb(skb
)->mh
->attrlen
>
698 FIELD_SIZEOF(struct sk_buff
, cb
))
700 if (skb_copy_bits(skb
, *offset
, mrp_cb(skb
)->attrvalue
,
701 mrp_cb(skb
)->mh
->attrlen
) < 0)
703 *offset
+= mrp_cb(skb
)->mh
->attrlen
;
705 /* In a VectorAttribute, the Vector contains events which are packed
706 * three to a byte. We process one byte of the Vector at a time.
709 if (skb_copy_bits(skb
, *offset
, &vaevents
,
710 sizeof(vaevents
)) < 0)
712 *offset
+= sizeof(vaevents
);
714 /* Extract and process the first event. */
715 vaevent
= vaevents
/ (__MRP_VECATTR_EVENT_MAX
*
716 __MRP_VECATTR_EVENT_MAX
);
717 if (vaevent
>= __MRP_VECATTR_EVENT_MAX
) {
718 /* The byte is malformed; stop processing. */
721 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
723 /* If present, extract and process the second event. */
726 mrp_attrvalue_inc(mrp_cb(skb
)->attrvalue
,
727 mrp_cb(skb
)->mh
->attrlen
);
728 vaevents
%= (__MRP_VECATTR_EVENT_MAX
*
729 __MRP_VECATTR_EVENT_MAX
);
730 vaevent
= vaevents
/ __MRP_VECATTR_EVENT_MAX
;
731 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
733 /* If present, extract and process the third event. */
736 mrp_attrvalue_inc(mrp_cb(skb
)->attrvalue
,
737 mrp_cb(skb
)->mh
->attrlen
);
738 vaevents
%= __MRP_VECATTR_EVENT_MAX
;
740 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
745 static int mrp_pdu_parse_msg(struct mrp_applicant
*app
, struct sk_buff
*skb
,
748 struct mrp_msg_hdr _mh
;
750 mrp_cb(skb
)->mh
= skb_header_pointer(skb
, *offset
, sizeof(_mh
), &_mh
);
751 if (!mrp_cb(skb
)->mh
)
753 *offset
+= sizeof(_mh
);
755 if (mrp_cb(skb
)->mh
->attrtype
== 0 ||
756 mrp_cb(skb
)->mh
->attrtype
> app
->app
->maxattr
||
757 mrp_cb(skb
)->mh
->attrlen
== 0)
760 while (skb
->len
> *offset
) {
761 if (mrp_pdu_parse_end_mark(skb
, offset
) < 0)
763 if (mrp_pdu_parse_vecattr(app
, skb
, offset
) < 0)
769 static int mrp_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
770 struct packet_type
*pt
, struct net_device
*orig_dev
)
772 struct mrp_application
*appl
= container_of(pt
, struct mrp_application
,
774 struct mrp_port
*port
;
775 struct mrp_applicant
*app
;
776 struct mrp_pdu_hdr _ph
;
777 const struct mrp_pdu_hdr
*ph
;
778 int offset
= skb_network_offset(skb
);
780 /* If the interface is in promiscuous mode, drop the packet if
781 * it was unicast to another host.
783 if (unlikely(skb
->pkt_type
== PACKET_OTHERHOST
))
785 skb
= skb_share_check(skb
, GFP_ATOMIC
);
788 port
= rcu_dereference(dev
->mrp_port
);
791 app
= rcu_dereference(port
->applicants
[appl
->type
]);
795 ph
= skb_header_pointer(skb
, offset
, sizeof(_ph
), &_ph
);
798 offset
+= sizeof(_ph
);
800 if (ph
->version
!= app
->app
->version
)
803 spin_lock(&app
->lock
);
804 while (skb
->len
> offset
) {
805 if (mrp_pdu_parse_end_mark(skb
, &offset
) < 0)
807 if (mrp_pdu_parse_msg(app
, skb
, &offset
) < 0)
810 spin_unlock(&app
->lock
);
816 static int mrp_init_port(struct net_device
*dev
)
818 struct mrp_port
*port
;
820 port
= kzalloc(sizeof(*port
), GFP_KERNEL
);
823 rcu_assign_pointer(dev
->mrp_port
, port
);
827 static void mrp_release_port(struct net_device
*dev
)
829 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
832 for (i
= 0; i
<= MRP_APPLICATION_MAX
; i
++) {
833 if (rtnl_dereference(port
->applicants
[i
]))
836 RCU_INIT_POINTER(dev
->mrp_port
, NULL
);
837 kfree_rcu(port
, rcu
);
840 int mrp_init_applicant(struct net_device
*dev
, struct mrp_application
*appl
)
842 struct mrp_applicant
*app
;
847 if (!rtnl_dereference(dev
->mrp_port
)) {
848 err
= mrp_init_port(dev
);
854 app
= kzalloc(sizeof(*app
), GFP_KERNEL
);
858 err
= dev_mc_add(dev
, appl
->group_address
);
865 spin_lock_init(&app
->lock
);
866 skb_queue_head_init(&app
->queue
);
867 rcu_assign_pointer(dev
->mrp_port
->applicants
[appl
->type
], app
);
868 timer_setup(&app
->join_timer
, mrp_join_timer
, 0);
869 mrp_join_timer_arm(app
);
870 timer_setup(&app
->periodic_timer
, mrp_periodic_timer
, 0);
871 mrp_periodic_timer_arm(app
);
877 mrp_release_port(dev
);
881 EXPORT_SYMBOL_GPL(mrp_init_applicant
);
883 void mrp_uninit_applicant(struct net_device
*dev
, struct mrp_application
*appl
)
885 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
886 struct mrp_applicant
*app
= rtnl_dereference(
887 port
->applicants
[appl
->type
]);
891 RCU_INIT_POINTER(port
->applicants
[appl
->type
], NULL
);
893 /* Delete timer and generate a final TX event to flush out
894 * all pending messages before the applicant is gone.
896 del_timer_sync(&app
->join_timer
);
897 del_timer_sync(&app
->periodic_timer
);
899 spin_lock_bh(&app
->lock
);
900 mrp_mad_event(app
, MRP_EVENT_TX
);
902 spin_unlock_bh(&app
->lock
);
906 dev_mc_del(dev
, appl
->group_address
);
908 mrp_release_port(dev
);
910 EXPORT_SYMBOL_GPL(mrp_uninit_applicant
);
912 int mrp_register_application(struct mrp_application
*appl
)
914 appl
->pkttype
.func
= mrp_rcv
;
915 dev_add_pack(&appl
->pkttype
);
918 EXPORT_SYMBOL_GPL(mrp_register_application
);
920 void mrp_unregister_application(struct mrp_application
*appl
)
922 dev_remove_pack(&appl
->pkttype
);
924 EXPORT_SYMBOL_GPL(mrp_unregister_application
);