1 // SPDX-License-Identifier: GPL-2.0-only
3 * IEEE 802.1Q Multiple Registration Protocol (MRP)
5 * Copyright (c) 2012 Massachusetts Institute of Technology
7 * Adapted from code in net/802/garp.c
8 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
10 #include <linux/kernel.h>
11 #include <linux/timer.h>
12 #include <linux/skbuff.h>
13 #include <linux/netdevice.h>
14 #include <linux/etherdevice.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
19 #include <asm/unaligned.h>
21 static unsigned int mrp_join_time __read_mostly
= 200;
22 module_param(mrp_join_time
, uint
, 0644);
23 MODULE_PARM_DESC(mrp_join_time
, "Join time in ms (default 200ms)");
25 static unsigned int mrp_periodic_time __read_mostly
= 1000;
26 module_param(mrp_periodic_time
, uint
, 0644);
27 MODULE_PARM_DESC(mrp_periodic_time
, "Periodic time in ms (default 1s)");
29 MODULE_LICENSE("GPL");
32 mrp_applicant_state_table
[MRP_APPLICANT_MAX
+ 1][MRP_EVENT_MAX
+ 1] = {
33 [MRP_APPLICANT_VO
] = {
34 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
35 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VP
,
36 [MRP_EVENT_LV
] = MRP_APPLICANT_VO
,
37 [MRP_EVENT_TX
] = MRP_APPLICANT_VO
,
38 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VO
,
39 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AO
,
40 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VO
,
41 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VO
,
42 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VO
,
43 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
44 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
45 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
46 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VO
,
48 [MRP_APPLICANT_VP
] = {
49 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
50 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VP
,
51 [MRP_EVENT_LV
] = MRP_APPLICANT_VO
,
52 [MRP_EVENT_TX
] = MRP_APPLICANT_AA
,
53 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VP
,
54 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AP
,
55 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VP
,
56 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VP
,
57 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VP
,
58 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
59 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
60 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
61 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VP
,
63 [MRP_APPLICANT_VN
] = {
64 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
65 [MRP_EVENT_JOIN
] = MRP_APPLICANT_VN
,
66 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
67 [MRP_EVENT_TX
] = MRP_APPLICANT_AN
,
68 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_VN
,
69 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_VN
,
70 [MRP_EVENT_R_IN
] = MRP_APPLICANT_VN
,
71 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_VN
,
72 [MRP_EVENT_R_MT
] = MRP_APPLICANT_VN
,
73 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VN
,
74 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VN
,
75 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VN
,
76 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_VN
,
78 [MRP_APPLICANT_AN
] = {
79 [MRP_EVENT_NEW
] = MRP_APPLICANT_AN
,
80 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AN
,
81 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
82 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
83 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AN
,
84 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_AN
,
85 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AN
,
86 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AN
,
87 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AN
,
88 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VN
,
89 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VN
,
90 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VN
,
91 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AN
,
93 [MRP_APPLICANT_AA
] = {
94 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
95 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AA
,
96 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
97 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
98 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AA
,
99 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QA
,
100 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AA
,
101 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AA
,
102 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AA
,
103 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
104 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
105 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
106 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AA
,
108 [MRP_APPLICANT_QA
] = {
109 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
110 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QA
,
111 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
112 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
113 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QA
,
114 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QA
,
115 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QA
,
116 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AA
,
117 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AA
,
118 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
119 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
120 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
121 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AA
,
123 [MRP_APPLICANT_LA
] = {
124 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
125 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AA
,
126 [MRP_EVENT_LV
] = MRP_APPLICANT_LA
,
127 [MRP_EVENT_TX
] = MRP_APPLICANT_VO
,
128 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_LA
,
129 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_LA
,
130 [MRP_EVENT_R_IN
] = MRP_APPLICANT_LA
,
131 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_LA
,
132 [MRP_EVENT_R_MT
] = MRP_APPLICANT_LA
,
133 [MRP_EVENT_R_LV
] = MRP_APPLICANT_LA
,
134 [MRP_EVENT_R_LA
] = MRP_APPLICANT_LA
,
135 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_LA
,
136 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_LA
,
138 [MRP_APPLICANT_AO
] = {
139 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
140 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AP
,
141 [MRP_EVENT_LV
] = MRP_APPLICANT_AO
,
142 [MRP_EVENT_TX
] = MRP_APPLICANT_AO
,
143 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AO
,
144 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QO
,
145 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AO
,
146 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AO
,
147 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AO
,
148 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
149 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
150 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
151 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AO
,
153 [MRP_APPLICANT_QO
] = {
154 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
155 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QP
,
156 [MRP_EVENT_LV
] = MRP_APPLICANT_QO
,
157 [MRP_EVENT_TX
] = MRP_APPLICANT_QO
,
158 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QO
,
159 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QO
,
160 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QO
,
161 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AO
,
162 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AO
,
163 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VO
,
164 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VO
,
165 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VO
,
166 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_QO
,
168 [MRP_APPLICANT_AP
] = {
169 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
170 [MRP_EVENT_JOIN
] = MRP_APPLICANT_AP
,
171 [MRP_EVENT_LV
] = MRP_APPLICANT_AO
,
172 [MRP_EVENT_TX
] = MRP_APPLICANT_QA
,
173 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_AP
,
174 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QP
,
175 [MRP_EVENT_R_IN
] = MRP_APPLICANT_AP
,
176 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AP
,
177 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AP
,
178 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
179 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
180 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
181 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AP
,
183 [MRP_APPLICANT_QP
] = {
184 [MRP_EVENT_NEW
] = MRP_APPLICANT_VN
,
185 [MRP_EVENT_JOIN
] = MRP_APPLICANT_QP
,
186 [MRP_EVENT_LV
] = MRP_APPLICANT_QO
,
187 [MRP_EVENT_TX
] = MRP_APPLICANT_QP
,
188 [MRP_EVENT_R_NEW
] = MRP_APPLICANT_QP
,
189 [MRP_EVENT_R_JOIN_IN
] = MRP_APPLICANT_QP
,
190 [MRP_EVENT_R_IN
] = MRP_APPLICANT_QP
,
191 [MRP_EVENT_R_JOIN_MT
] = MRP_APPLICANT_AP
,
192 [MRP_EVENT_R_MT
] = MRP_APPLICANT_AP
,
193 [MRP_EVENT_R_LV
] = MRP_APPLICANT_VP
,
194 [MRP_EVENT_R_LA
] = MRP_APPLICANT_VP
,
195 [MRP_EVENT_REDECLARE
] = MRP_APPLICANT_VP
,
196 [MRP_EVENT_PERIODIC
] = MRP_APPLICANT_AP
,
201 mrp_tx_action_table
[MRP_APPLICANT_MAX
+ 1] = {
202 [MRP_APPLICANT_VO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
203 [MRP_APPLICANT_VP
] = MRP_TX_ACTION_S_JOIN_IN
,
204 [MRP_APPLICANT_VN
] = MRP_TX_ACTION_S_NEW
,
205 [MRP_APPLICANT_AN
] = MRP_TX_ACTION_S_NEW
,
206 [MRP_APPLICANT_AA
] = MRP_TX_ACTION_S_JOIN_IN
,
207 [MRP_APPLICANT_QA
] = MRP_TX_ACTION_S_JOIN_IN_OPTIONAL
,
208 [MRP_APPLICANT_LA
] = MRP_TX_ACTION_S_LV
,
209 [MRP_APPLICANT_AO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
210 [MRP_APPLICANT_QO
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
211 [MRP_APPLICANT_AP
] = MRP_TX_ACTION_S_JOIN_IN
,
212 [MRP_APPLICANT_QP
] = MRP_TX_ACTION_S_IN_OPTIONAL
,
215 static void mrp_attrvalue_inc(void *value
, u8 len
)
219 /* Add 1 to the last byte. If it becomes zero,
220 * go to the previous byte and repeat.
222 while (len
> 0 && !++v
[--len
])
226 static int mrp_attr_cmp(const struct mrp_attr
*attr
,
227 const void *value
, u8 len
, u8 type
)
229 if (attr
->type
!= type
)
230 return attr
->type
- type
;
231 if (attr
->len
!= len
)
232 return attr
->len
- len
;
233 return memcmp(attr
->value
, value
, len
);
236 static struct mrp_attr
*mrp_attr_lookup(const struct mrp_applicant
*app
,
237 const void *value
, u8 len
, u8 type
)
239 struct rb_node
*parent
= app
->mad
.rb_node
;
240 struct mrp_attr
*attr
;
244 attr
= rb_entry(parent
, struct mrp_attr
, node
);
245 d
= mrp_attr_cmp(attr
, value
, len
, type
);
247 parent
= parent
->rb_left
;
249 parent
= parent
->rb_right
;
256 static struct mrp_attr
*mrp_attr_create(struct mrp_applicant
*app
,
257 const void *value
, u8 len
, u8 type
)
259 struct rb_node
*parent
= NULL
, **p
= &app
->mad
.rb_node
;
260 struct mrp_attr
*attr
;
265 attr
= rb_entry(parent
, struct mrp_attr
, node
);
266 d
= mrp_attr_cmp(attr
, value
, len
, type
);
268 p
= &parent
->rb_left
;
270 p
= &parent
->rb_right
;
272 /* The attribute already exists; re-use it. */
276 attr
= kmalloc(sizeof(*attr
) + len
, GFP_ATOMIC
);
279 attr
->state
= MRP_APPLICANT_VO
;
282 memcpy(attr
->value
, value
, len
);
284 rb_link_node(&attr
->node
, parent
, p
);
285 rb_insert_color(&attr
->node
, &app
->mad
);
289 static void mrp_attr_destroy(struct mrp_applicant
*app
, struct mrp_attr
*attr
)
291 rb_erase(&attr
->node
, &app
->mad
);
295 static void mrp_attr_destroy_all(struct mrp_applicant
*app
)
297 struct rb_node
*node
, *next
;
298 struct mrp_attr
*attr
;
300 for (node
= rb_first(&app
->mad
);
301 next
= node
? rb_next(node
) : NULL
, node
!= NULL
;
303 attr
= rb_entry(node
, struct mrp_attr
, node
);
304 mrp_attr_destroy(app
, attr
);
308 static int mrp_pdu_init(struct mrp_applicant
*app
)
311 struct mrp_pdu_hdr
*ph
;
313 skb
= alloc_skb(app
->dev
->mtu
+ LL_RESERVED_SPACE(app
->dev
),
319 skb
->protocol
= app
->app
->pkttype
.type
;
320 skb_reserve(skb
, LL_RESERVED_SPACE(app
->dev
));
321 skb_reset_network_header(skb
);
322 skb_reset_transport_header(skb
);
324 ph
= __skb_put(skb
, sizeof(*ph
));
325 ph
->version
= app
->app
->version
;
331 static int mrp_pdu_append_end_mark(struct mrp_applicant
*app
)
335 if (skb_tailroom(app
->pdu
) < sizeof(*endmark
))
337 endmark
= __skb_put(app
->pdu
, sizeof(*endmark
));
338 put_unaligned(MRP_END_MARK
, endmark
);
342 static void mrp_pdu_queue(struct mrp_applicant
*app
)
347 if (mrp_cb(app
->pdu
)->mh
)
348 mrp_pdu_append_end_mark(app
);
349 mrp_pdu_append_end_mark(app
);
351 dev_hard_header(app
->pdu
, app
->dev
, ntohs(app
->app
->pkttype
.type
),
352 app
->app
->group_address
, app
->dev
->dev_addr
,
355 skb_queue_tail(&app
->queue
, app
->pdu
);
359 static void mrp_queue_xmit(struct mrp_applicant
*app
)
363 while ((skb
= skb_dequeue(&app
->queue
)))
367 static int mrp_pdu_append_msg_hdr(struct mrp_applicant
*app
,
368 u8 attrtype
, u8 attrlen
)
370 struct mrp_msg_hdr
*mh
;
372 if (mrp_cb(app
->pdu
)->mh
) {
373 if (mrp_pdu_append_end_mark(app
) < 0)
375 mrp_cb(app
->pdu
)->mh
= NULL
;
376 mrp_cb(app
->pdu
)->vah
= NULL
;
379 if (skb_tailroom(app
->pdu
) < sizeof(*mh
))
381 mh
= __skb_put(app
->pdu
, sizeof(*mh
));
382 mh
->attrtype
= attrtype
;
383 mh
->attrlen
= attrlen
;
384 mrp_cb(app
->pdu
)->mh
= mh
;
388 static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant
*app
,
389 const void *firstattrvalue
, u8 attrlen
)
391 struct mrp_vecattr_hdr
*vah
;
393 if (skb_tailroom(app
->pdu
) < sizeof(*vah
) + attrlen
)
395 vah
= __skb_put(app
->pdu
, sizeof(*vah
) + attrlen
);
396 put_unaligned(0, &vah
->lenflags
);
397 memcpy(vah
->firstattrvalue
, firstattrvalue
, attrlen
);
398 mrp_cb(app
->pdu
)->vah
= vah
;
399 memcpy(mrp_cb(app
->pdu
)->attrvalue
, firstattrvalue
, attrlen
);
403 static int mrp_pdu_append_vecattr_event(struct mrp_applicant
*app
,
404 const struct mrp_attr
*attr
,
405 enum mrp_vecattr_event vaevent
)
412 err
= mrp_pdu_init(app
);
417 /* If there is no Message header in the PDU, or the Message header is
418 * for a different attribute type, add an EndMark (if necessary) and a
419 * new Message header to the PDU.
421 if (!mrp_cb(app
->pdu
)->mh
||
422 mrp_cb(app
->pdu
)->mh
->attrtype
!= attr
->type
||
423 mrp_cb(app
->pdu
)->mh
->attrlen
!= attr
->len
) {
424 if (mrp_pdu_append_msg_hdr(app
, attr
->type
, attr
->len
) < 0)
428 /* If there is no VectorAttribute header for this Message in the PDU,
429 * or this attribute's value does not sequentially follow the previous
430 * attribute's value, add a new VectorAttribute header to the PDU.
432 if (!mrp_cb(app
->pdu
)->vah
||
433 memcmp(mrp_cb(app
->pdu
)->attrvalue
, attr
->value
, attr
->len
)) {
434 if (mrp_pdu_append_vecattr_hdr(app
, attr
->value
, attr
->len
) < 0)
438 len
= be16_to_cpu(get_unaligned(&mrp_cb(app
->pdu
)->vah
->lenflags
));
441 /* Events are packed into Vectors in the PDU, three to a byte. Add a
442 * byte to the end of the Vector if necessary.
445 if (skb_tailroom(app
->pdu
) < sizeof(u8
))
447 vaevents
= __skb_put(app
->pdu
, sizeof(u8
));
449 vaevents
= (u8
*)(skb_tail_pointer(app
->pdu
) - sizeof(u8
));
454 *vaevents
= vaevent
* (__MRP_VECATTR_EVENT_MAX
*
455 __MRP_VECATTR_EVENT_MAX
);
458 *vaevents
+= vaevent
* __MRP_VECATTR_EVENT_MAX
;
461 *vaevents
+= vaevent
;
467 /* Increment the length of the VectorAttribute in the PDU, as well as
468 * the value of the next attribute that would continue its Vector.
470 put_unaligned(cpu_to_be16(++len
), &mrp_cb(app
->pdu
)->vah
->lenflags
);
471 mrp_attrvalue_inc(mrp_cb(app
->pdu
)->attrvalue
, attr
->len
);
480 static void mrp_attr_event(struct mrp_applicant
*app
,
481 struct mrp_attr
*attr
, enum mrp_event event
)
483 enum mrp_applicant_state state
;
485 state
= mrp_applicant_state_table
[attr
->state
][event
];
486 if (state
== MRP_APPLICANT_INVALID
) {
491 if (event
== MRP_EVENT_TX
) {
492 /* When appending the attribute fails, don't update its state
493 * in order to retry at the next TX event.
496 switch (mrp_tx_action_table
[attr
->state
]) {
497 case MRP_TX_ACTION_NONE
:
498 case MRP_TX_ACTION_S_JOIN_IN_OPTIONAL
:
499 case MRP_TX_ACTION_S_IN_OPTIONAL
:
501 case MRP_TX_ACTION_S_NEW
:
502 if (mrp_pdu_append_vecattr_event(
503 app
, attr
, MRP_VECATTR_EVENT_NEW
) < 0)
506 case MRP_TX_ACTION_S_JOIN_IN
:
507 if (mrp_pdu_append_vecattr_event(
508 app
, attr
, MRP_VECATTR_EVENT_JOIN_IN
) < 0)
511 case MRP_TX_ACTION_S_LV
:
512 if (mrp_pdu_append_vecattr_event(
513 app
, attr
, MRP_VECATTR_EVENT_LV
) < 0)
515 /* As a pure applicant, sending a leave message
516 * implies that the attribute was unregistered and
519 mrp_attr_destroy(app
, attr
);
529 int mrp_request_join(const struct net_device
*dev
,
530 const struct mrp_application
*appl
,
531 const void *value
, u8 len
, u8 type
)
533 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
534 struct mrp_applicant
*app
= rtnl_dereference(
535 port
->applicants
[appl
->type
]);
536 struct mrp_attr
*attr
;
538 if (sizeof(struct mrp_skb_cb
) + len
>
539 sizeof_field(struct sk_buff
, cb
))
542 spin_lock_bh(&app
->lock
);
543 attr
= mrp_attr_create(app
, value
, len
, type
);
545 spin_unlock_bh(&app
->lock
);
548 mrp_attr_event(app
, attr
, MRP_EVENT_JOIN
);
549 spin_unlock_bh(&app
->lock
);
552 EXPORT_SYMBOL_GPL(mrp_request_join
);
554 void mrp_request_leave(const struct net_device
*dev
,
555 const struct mrp_application
*appl
,
556 const void *value
, u8 len
, u8 type
)
558 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
559 struct mrp_applicant
*app
= rtnl_dereference(
560 port
->applicants
[appl
->type
]);
561 struct mrp_attr
*attr
;
563 if (sizeof(struct mrp_skb_cb
) + len
>
564 sizeof_field(struct sk_buff
, cb
))
567 spin_lock_bh(&app
->lock
);
568 attr
= mrp_attr_lookup(app
, value
, len
, type
);
570 spin_unlock_bh(&app
->lock
);
573 mrp_attr_event(app
, attr
, MRP_EVENT_LV
);
574 spin_unlock_bh(&app
->lock
);
576 EXPORT_SYMBOL_GPL(mrp_request_leave
);
578 static void mrp_mad_event(struct mrp_applicant
*app
, enum mrp_event event
)
580 struct rb_node
*node
, *next
;
581 struct mrp_attr
*attr
;
583 for (node
= rb_first(&app
->mad
);
584 next
= node
? rb_next(node
) : NULL
, node
!= NULL
;
586 attr
= rb_entry(node
, struct mrp_attr
, node
);
587 mrp_attr_event(app
, attr
, event
);
591 static void mrp_join_timer_arm(struct mrp_applicant
*app
)
595 delay
= (u64
)msecs_to_jiffies(mrp_join_time
) * prandom_u32() >> 32;
596 mod_timer(&app
->join_timer
, jiffies
+ delay
);
599 static void mrp_join_timer(struct timer_list
*t
)
601 struct mrp_applicant
*app
= from_timer(app
, t
, join_timer
);
603 spin_lock(&app
->lock
);
604 mrp_mad_event(app
, MRP_EVENT_TX
);
606 spin_unlock(&app
->lock
);
609 mrp_join_timer_arm(app
);
612 static void mrp_periodic_timer_arm(struct mrp_applicant
*app
)
614 mod_timer(&app
->periodic_timer
,
615 jiffies
+ msecs_to_jiffies(mrp_periodic_time
));
618 static void mrp_periodic_timer(struct timer_list
*t
)
620 struct mrp_applicant
*app
= from_timer(app
, t
, periodic_timer
);
622 spin_lock(&app
->lock
);
623 mrp_mad_event(app
, MRP_EVENT_PERIODIC
);
625 spin_unlock(&app
->lock
);
627 mrp_periodic_timer_arm(app
);
630 static int mrp_pdu_parse_end_mark(struct sk_buff
*skb
, int *offset
)
634 if (skb_copy_bits(skb
, *offset
, &endmark
, sizeof(endmark
)) < 0)
636 if (endmark
== MRP_END_MARK
) {
637 *offset
+= sizeof(endmark
);
643 static void mrp_pdu_parse_vecattr_event(struct mrp_applicant
*app
,
645 enum mrp_vecattr_event vaevent
)
647 struct mrp_attr
*attr
;
648 enum mrp_event event
;
650 attr
= mrp_attr_lookup(app
, mrp_cb(skb
)->attrvalue
,
651 mrp_cb(skb
)->mh
->attrlen
,
652 mrp_cb(skb
)->mh
->attrtype
);
657 case MRP_VECATTR_EVENT_NEW
:
658 event
= MRP_EVENT_R_NEW
;
660 case MRP_VECATTR_EVENT_JOIN_IN
:
661 event
= MRP_EVENT_R_JOIN_IN
;
663 case MRP_VECATTR_EVENT_IN
:
664 event
= MRP_EVENT_R_IN
;
666 case MRP_VECATTR_EVENT_JOIN_MT
:
667 event
= MRP_EVENT_R_JOIN_MT
;
669 case MRP_VECATTR_EVENT_MT
:
670 event
= MRP_EVENT_R_MT
;
672 case MRP_VECATTR_EVENT_LV
:
673 event
= MRP_EVENT_R_LV
;
679 mrp_attr_event(app
, attr
, event
);
682 static int mrp_pdu_parse_vecattr(struct mrp_applicant
*app
,
683 struct sk_buff
*skb
, int *offset
)
685 struct mrp_vecattr_hdr _vah
;
687 u8 vaevents
, vaevent
;
689 mrp_cb(skb
)->vah
= skb_header_pointer(skb
, *offset
, sizeof(_vah
),
691 if (!mrp_cb(skb
)->vah
)
693 *offset
+= sizeof(_vah
);
695 if (get_unaligned(&mrp_cb(skb
)->vah
->lenflags
) &
696 MRP_VECATTR_HDR_FLAG_LA
)
697 mrp_mad_event(app
, MRP_EVENT_R_LA
);
698 valen
= be16_to_cpu(get_unaligned(&mrp_cb(skb
)->vah
->lenflags
) &
699 MRP_VECATTR_HDR_LEN_MASK
);
701 /* The VectorAttribute structure in a PDU carries event information
702 * about one or more attributes having consecutive values. Only the
703 * value for the first attribute is contained in the structure. So
704 * we make a copy of that value, and then increment it each time we
705 * advance to the next event in its Vector.
707 if (sizeof(struct mrp_skb_cb
) + mrp_cb(skb
)->mh
->attrlen
>
708 sizeof_field(struct sk_buff
, cb
))
710 if (skb_copy_bits(skb
, *offset
, mrp_cb(skb
)->attrvalue
,
711 mrp_cb(skb
)->mh
->attrlen
) < 0)
713 *offset
+= mrp_cb(skb
)->mh
->attrlen
;
715 /* In a VectorAttribute, the Vector contains events which are packed
716 * three to a byte. We process one byte of the Vector at a time.
719 if (skb_copy_bits(skb
, *offset
, &vaevents
,
720 sizeof(vaevents
)) < 0)
722 *offset
+= sizeof(vaevents
);
724 /* Extract and process the first event. */
725 vaevent
= vaevents
/ (__MRP_VECATTR_EVENT_MAX
*
726 __MRP_VECATTR_EVENT_MAX
);
727 if (vaevent
>= __MRP_VECATTR_EVENT_MAX
) {
728 /* The byte is malformed; stop processing. */
731 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
733 /* If present, extract and process the second event. */
736 mrp_attrvalue_inc(mrp_cb(skb
)->attrvalue
,
737 mrp_cb(skb
)->mh
->attrlen
);
738 vaevents
%= (__MRP_VECATTR_EVENT_MAX
*
739 __MRP_VECATTR_EVENT_MAX
);
740 vaevent
= vaevents
/ __MRP_VECATTR_EVENT_MAX
;
741 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
743 /* If present, extract and process the third event. */
746 mrp_attrvalue_inc(mrp_cb(skb
)->attrvalue
,
747 mrp_cb(skb
)->mh
->attrlen
);
748 vaevents
%= __MRP_VECATTR_EVENT_MAX
;
750 mrp_pdu_parse_vecattr_event(app
, skb
, vaevent
);
755 static int mrp_pdu_parse_msg(struct mrp_applicant
*app
, struct sk_buff
*skb
,
758 struct mrp_msg_hdr _mh
;
760 mrp_cb(skb
)->mh
= skb_header_pointer(skb
, *offset
, sizeof(_mh
), &_mh
);
761 if (!mrp_cb(skb
)->mh
)
763 *offset
+= sizeof(_mh
);
765 if (mrp_cb(skb
)->mh
->attrtype
== 0 ||
766 mrp_cb(skb
)->mh
->attrtype
> app
->app
->maxattr
||
767 mrp_cb(skb
)->mh
->attrlen
== 0)
770 while (skb
->len
> *offset
) {
771 if (mrp_pdu_parse_end_mark(skb
, offset
) < 0)
773 if (mrp_pdu_parse_vecattr(app
, skb
, offset
) < 0)
779 static int mrp_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
780 struct packet_type
*pt
, struct net_device
*orig_dev
)
782 struct mrp_application
*appl
= container_of(pt
, struct mrp_application
,
784 struct mrp_port
*port
;
785 struct mrp_applicant
*app
;
786 struct mrp_pdu_hdr _ph
;
787 const struct mrp_pdu_hdr
*ph
;
788 int offset
= skb_network_offset(skb
);
790 /* If the interface is in promiscuous mode, drop the packet if
791 * it was unicast to another host.
793 if (unlikely(skb
->pkt_type
== PACKET_OTHERHOST
))
795 skb
= skb_share_check(skb
, GFP_ATOMIC
);
798 port
= rcu_dereference(dev
->mrp_port
);
801 app
= rcu_dereference(port
->applicants
[appl
->type
]);
805 ph
= skb_header_pointer(skb
, offset
, sizeof(_ph
), &_ph
);
808 offset
+= sizeof(_ph
);
810 if (ph
->version
!= app
->app
->version
)
813 spin_lock(&app
->lock
);
814 while (skb
->len
> offset
) {
815 if (mrp_pdu_parse_end_mark(skb
, &offset
) < 0)
817 if (mrp_pdu_parse_msg(app
, skb
, &offset
) < 0)
820 spin_unlock(&app
->lock
);
826 static int mrp_init_port(struct net_device
*dev
)
828 struct mrp_port
*port
;
830 port
= kzalloc(sizeof(*port
), GFP_KERNEL
);
833 rcu_assign_pointer(dev
->mrp_port
, port
);
837 static void mrp_release_port(struct net_device
*dev
)
839 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
842 for (i
= 0; i
<= MRP_APPLICATION_MAX
; i
++) {
843 if (rtnl_dereference(port
->applicants
[i
]))
846 RCU_INIT_POINTER(dev
->mrp_port
, NULL
);
847 kfree_rcu(port
, rcu
);
850 int mrp_init_applicant(struct net_device
*dev
, struct mrp_application
*appl
)
852 struct mrp_applicant
*app
;
857 if (!rtnl_dereference(dev
->mrp_port
)) {
858 err
= mrp_init_port(dev
);
864 app
= kzalloc(sizeof(*app
), GFP_KERNEL
);
868 err
= dev_mc_add(dev
, appl
->group_address
);
875 spin_lock_init(&app
->lock
);
876 skb_queue_head_init(&app
->queue
);
877 rcu_assign_pointer(dev
->mrp_port
->applicants
[appl
->type
], app
);
878 timer_setup(&app
->join_timer
, mrp_join_timer
, 0);
879 mrp_join_timer_arm(app
);
880 timer_setup(&app
->periodic_timer
, mrp_periodic_timer
, 0);
881 mrp_periodic_timer_arm(app
);
887 mrp_release_port(dev
);
891 EXPORT_SYMBOL_GPL(mrp_init_applicant
);
893 void mrp_uninit_applicant(struct net_device
*dev
, struct mrp_application
*appl
)
895 struct mrp_port
*port
= rtnl_dereference(dev
->mrp_port
);
896 struct mrp_applicant
*app
= rtnl_dereference(
897 port
->applicants
[appl
->type
]);
901 RCU_INIT_POINTER(port
->applicants
[appl
->type
], NULL
);
903 /* Delete timer and generate a final TX event to flush out
904 * all pending messages before the applicant is gone.
906 del_timer_sync(&app
->join_timer
);
907 del_timer_sync(&app
->periodic_timer
);
909 spin_lock_bh(&app
->lock
);
910 mrp_mad_event(app
, MRP_EVENT_TX
);
911 mrp_attr_destroy_all(app
);
913 spin_unlock_bh(&app
->lock
);
917 dev_mc_del(dev
, appl
->group_address
);
919 mrp_release_port(dev
);
921 EXPORT_SYMBOL_GPL(mrp_uninit_applicant
);
923 int mrp_register_application(struct mrp_application
*appl
)
925 appl
->pkttype
.func
= mrp_rcv
;
926 dev_add_pack(&appl
->pkttype
);
929 EXPORT_SYMBOL_GPL(mrp_register_application
);
931 void mrp_unregister_application(struct mrp_application
*appl
)
933 dev_remove_pack(&appl
->pkttype
);
935 EXPORT_SYMBOL_GPL(mrp_unregister_application
);