linux/net/802/mrp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *      IEEE 802.1Q Multiple Registration Protocol (MRP)
   4 *
   5 *      Copyright (c) 2012 Massachusetts Institute of Technology
   6 *
   7 *      Adapted from code in net/802/garp.c
   8 *      Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
   9 */
  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>
  18#include <net/mrp.h>
  19#include <asm/unaligned.h>
  20
  21static unsigned int mrp_join_time __read_mostly = 200;
  22module_param(mrp_join_time, uint, 0644);
  23MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");
  24
  25static unsigned int mrp_periodic_time __read_mostly = 1000;
  26module_param(mrp_periodic_time, uint, 0644);
  27MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)");
  28
  29MODULE_LICENSE("GPL");
  30
  31static const u8
  32mrp_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,
  47        },
  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,
  62        },
  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,
  77        },
  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,
  92        },
  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,
 107        },
 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,
 122        },
 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,
 137        },
 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,
 152        },
 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,
 167        },
 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,
 182        },
 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,
 197        },
 198};
 199
 200static const u8
 201mrp_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,
 213};
 214
 215static void mrp_attrvalue_inc(void *value, u8 len)
 216{
 217        u8 *v = (u8 *)value;
 218
 219        /* Add 1 to the last byte. If it becomes zero,
 220         * go to the previous byte and repeat.
 221         */
 222        while (len > 0 && !++v[--len])
 223                ;
 224}
 225
 226static int mrp_attr_cmp(const struct mrp_attr *attr,
 227                         const void *value, u8 len, u8 type)
 228{
 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);
 234}
 235
 236static struct mrp_attr *mrp_attr_lookup(const struct mrp_applicant *app,
 237                                        const void *value, u8 len, u8 type)
 238{
 239        struct rb_node *parent = app->mad.rb_node;
 240        struct mrp_attr *attr;
 241        int d;
 242
 243        while (parent) {
 244                attr = rb_entry(parent, struct mrp_attr, node);
 245                d = mrp_attr_cmp(attr, value, len, type);
 246                if (d > 0)
 247                        parent = parent->rb_left;
 248                else if (d < 0)
 249                        parent = parent->rb_right;
 250                else
 251                        return attr;
 252        }
 253        return NULL;
 254}
 255
 256static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app,
 257                                        const void *value, u8 len, u8 type)
 258{
 259        struct rb_node *parent = NULL, **p = &app->mad.rb_node;
 260        struct mrp_attr *attr;
 261        int d;
 262
 263        while (*p) {
 264                parent = *p;
 265                attr = rb_entry(parent, struct mrp_attr, node);
 266                d = mrp_attr_cmp(attr, value, len, type);
 267                if (d > 0)
 268                        p = &parent->rb_left;
 269                else if (d < 0)
 270                        p = &parent->rb_right;
 271                else {
 272                        /* The attribute already exists; re-use it. */
 273                        return attr;
 274                }
 275        }
 276        attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
 277        if (!attr)
 278                return attr;
 279        attr->state = MRP_APPLICANT_VO;
 280        attr->type  = type;
 281        attr->len   = len;
 282        memcpy(attr->value, value, len);
 283
 284        rb_link_node(&attr->node, parent, p);
 285        rb_insert_color(&attr->node, &app->mad);
 286        return attr;
 287}
 288
 289static void mrp_attr_destroy(struct mrp_applicant *app, struct mrp_attr *attr)
 290{
 291        rb_erase(&attr->node, &app->mad);
 292        kfree(attr);
 293}
 294
 295static void mrp_attr_destroy_all(struct mrp_applicant *app)
 296{
 297        struct rb_node *node, *next;
 298        struct mrp_attr *attr;
 299
 300        for (node = rb_first(&app->mad);
 301             next = node ? rb_next(node) : NULL, node != NULL;
 302             node = next) {
 303                attr = rb_entry(node, struct mrp_attr, node);
 304                mrp_attr_destroy(app, attr);
 305        }
 306}
 307
 308static int mrp_pdu_init(struct mrp_applicant *app)
 309{
 310        struct sk_buff *skb;
 311        struct mrp_pdu_hdr *ph;
 312
 313        skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev),
 314                        GFP_ATOMIC);
 315        if (!skb)
 316                return -ENOMEM;
 317
 318        skb->dev = 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);
 323
 324        ph = __skb_put(skb, sizeof(*ph));
 325        ph->version = app->app->version;
 326
 327        app->pdu = skb;
 328        return 0;
 329}
 330
 331static int mrp_pdu_append_end_mark(struct mrp_applicant *app)
 332{
 333        __be16 *endmark;
 334
 335        if (skb_tailroom(app->pdu) < sizeof(*endmark))
 336                return -1;
 337        endmark = __skb_put(app->pdu, sizeof(*endmark));
 338        put_unaligned(MRP_END_MARK, endmark);
 339        return 0;
 340}
 341
 342static void mrp_pdu_queue(struct mrp_applicant *app)
 343{
 344        if (!app->pdu)
 345                return;
 346
 347        if (mrp_cb(app->pdu)->mh)
 348                mrp_pdu_append_end_mark(app);
 349        mrp_pdu_append_end_mark(app);
 350
 351        dev_hard_header(app->pdu, app->dev, ntohs(app->app->pkttype.type),
 352                        app->app->group_address, app->dev->dev_addr,
 353                        app->pdu->len);
 354
 355        skb_queue_tail(&app->queue, app->pdu);
 356        app->pdu = NULL;
 357}
 358
 359static void mrp_queue_xmit(struct mrp_applicant *app)
 360{
 361        struct sk_buff *skb;
 362
 363        while ((skb = skb_dequeue(&app->queue)))
 364                dev_queue_xmit(skb);
 365}
 366
 367static int mrp_pdu_append_msg_hdr(struct mrp_applicant *app,
 368                                  u8 attrtype, u8 attrlen)
 369{
 370        struct mrp_msg_hdr *mh;
 371
 372        if (mrp_cb(app->pdu)->mh) {
 373                if (mrp_pdu_append_end_mark(app) < 0)
 374                        return -1;
 375                mrp_cb(app->pdu)->mh = NULL;
 376                mrp_cb(app->pdu)->vah = NULL;
 377        }
 378
 379        if (skb_tailroom(app->pdu) < sizeof(*mh))
 380                return -1;
 381        mh = __skb_put(app->pdu, sizeof(*mh));
 382        mh->attrtype = attrtype;
 383        mh->attrlen = attrlen;
 384        mrp_cb(app->pdu)->mh = mh;
 385        return 0;
 386}
 387
 388static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant *app,
 389                                      const void *firstattrvalue, u8 attrlen)
 390{
 391        struct mrp_vecattr_hdr *vah;
 392
 393        if (skb_tailroom(app->pdu) < sizeof(*vah) + attrlen)
 394                return -1;
 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);
 400        return 0;
 401}
 402
 403static int mrp_pdu_append_vecattr_event(struct mrp_applicant *app,
 404                                        const struct mrp_attr *attr,
 405                                        enum mrp_vecattr_event vaevent)
 406{
 407        u16 len, pos;
 408        u8 *vaevents;
 409        int err;
 410again:
 411        if (!app->pdu) {
 412                err = mrp_pdu_init(app);
 413                if (err < 0)
 414                        return err;
 415        }
 416
 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.
 420         */
 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)
 425                        goto queue;
 426        }
 427
 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.
 431         */
 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)
 435                        goto queue;
 436        }
 437
 438        len = be16_to_cpu(get_unaligned(&mrp_cb(app->pdu)->vah->lenflags));
 439        pos = len % 3;
 440
 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.
 443         */
 444        if (!pos) {
 445                if (skb_tailroom(app->pdu) < sizeof(u8))
 446                        goto queue;
 447                vaevents = __skb_put(app->pdu, sizeof(u8));
 448        } else {
 449                vaevents = (u8 *)(skb_tail_pointer(app->pdu) - sizeof(u8));
 450        }
 451
 452        switch (pos) {
 453        case 0:
 454                *vaevents = vaevent * (__MRP_VECATTR_EVENT_MAX *
 455                                       __MRP_VECATTR_EVENT_MAX);
 456                break;
 457        case 1:
 458                *vaevents += vaevent * __MRP_VECATTR_EVENT_MAX;
 459                break;
 460        case 2:
 461                *vaevents += vaevent;
 462                break;
 463        default:
 464                WARN_ON(1);
 465        }
 466
 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.
 469         */
 470        put_unaligned(cpu_to_be16(++len), &mrp_cb(app->pdu)->vah->lenflags);
 471        mrp_attrvalue_inc(mrp_cb(app->pdu)->attrvalue, attr->len);
 472
 473        return 0;
 474
 475queue:
 476        mrp_pdu_queue(app);
 477        goto again;
 478}
 479
 480static void mrp_attr_event(struct mrp_applicant *app,
 481                           struct mrp_attr *attr, enum mrp_event event)
 482{
 483        enum mrp_applicant_state state;
 484
 485        state = mrp_applicant_state_table[attr->state][event];
 486        if (state == MRP_APPLICANT_INVALID) {
 487                WARN_ON(1);
 488                return;
 489        }
 490
 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.
 494                 */
 495
 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:
 500                        break;
 501                case MRP_TX_ACTION_S_NEW:
 502                        if (mrp_pdu_append_vecattr_event(
 503                                    app, attr, MRP_VECATTR_EVENT_NEW) < 0)
 504                                return;
 505                        break;
 506                case MRP_TX_ACTION_S_JOIN_IN:
 507                        if (mrp_pdu_append_vecattr_event(
 508                                    app, attr, MRP_VECATTR_EVENT_JOIN_IN) < 0)
 509                                return;
 510                        break;
 511                case MRP_TX_ACTION_S_LV:
 512                        if (mrp_pdu_append_vecattr_event(
 513                                    app, attr, MRP_VECATTR_EVENT_LV) < 0)
 514                                return;
 515                        /* As a pure applicant, sending a leave message
 516                         * implies that the attribute was unregistered and
 517                         * can be destroyed.
 518                         */
 519                        mrp_attr_destroy(app, attr);
 520                        return;
 521                default:
 522                        WARN_ON(1);
 523                }
 524        }
 525
 526        attr->state = state;
 527}
 528
 529int mrp_request_join(const struct net_device *dev,
 530                     const struct mrp_application *appl,
 531                     const void *value, u8 len, u8 type)
 532{
 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;
 537
 538        if (sizeof(struct mrp_skb_cb) + len >
 539            sizeof_field(struct sk_buff, cb))
 540                return -ENOMEM;
 541
 542        spin_lock_bh(&app->lock);
 543        attr = mrp_attr_create(app, value, len, type);
 544        if (!attr) {
 545                spin_unlock_bh(&app->lock);
 546                return -ENOMEM;
 547        }
 548        mrp_attr_event(app, attr, MRP_EVENT_JOIN);
 549        spin_unlock_bh(&app->lock);
 550        return 0;
 551}
 552EXPORT_SYMBOL_GPL(mrp_request_join);
 553
 554void mrp_request_leave(const struct net_device *dev,
 555                       const struct mrp_application *appl,
 556                       const void *value, u8 len, u8 type)
 557{
 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;
 562
 563        if (sizeof(struct mrp_skb_cb) + len >
 564            sizeof_field(struct sk_buff, cb))
 565                return;
 566
 567        spin_lock_bh(&app->lock);
 568        attr = mrp_attr_lookup(app, value, len, type);
 569        if (!attr) {
 570                spin_unlock_bh(&app->lock);
 571                return;
 572        }
 573        mrp_attr_event(app, attr, MRP_EVENT_LV);
 574        spin_unlock_bh(&app->lock);
 575}
 576EXPORT_SYMBOL_GPL(mrp_request_leave);
 577
 578static void mrp_mad_event(struct mrp_applicant *app, enum mrp_event event)
 579{
 580        struct rb_node *node, *next;
 581        struct mrp_attr *attr;
 582
 583        for (node = rb_first(&app->mad);
 584             next = node ? rb_next(node) : NULL, node != NULL;
 585             node = next) {
 586                attr = rb_entry(node, struct mrp_attr, node);
 587                mrp_attr_event(app, attr, event);
 588        }
 589}
 590
 591static void mrp_join_timer_arm(struct mrp_applicant *app)
 592{
 593        unsigned long delay;
 594
 595        delay = (u64)msecs_to_jiffies(mrp_join_time) * prandom_u32() >> 32;
 596        mod_timer(&app->join_timer, jiffies + delay);
 597}
 598
 599static void mrp_join_timer(struct timer_list *t)
 600{
 601        struct mrp_applicant *app = from_timer(app, t, join_timer);
 602
 603        spin_lock(&app->lock);
 604        mrp_mad_event(app, MRP_EVENT_TX);
 605        mrp_pdu_queue(app);
 606        spin_unlock(&app->lock);
 607
 608        mrp_queue_xmit(app);
 609        mrp_join_timer_arm(app);
 610}
 611
 612static void mrp_periodic_timer_arm(struct mrp_applicant *app)
 613{
 614        mod_timer(&app->periodic_timer,
 615                  jiffies + msecs_to_jiffies(mrp_periodic_time));
 616}
 617
 618static void mrp_periodic_timer(struct timer_list *t)
 619{
 620        struct mrp_applicant *app = from_timer(app, t, periodic_timer);
 621
 622        spin_lock(&app->lock);
 623        mrp_mad_event(app, MRP_EVENT_PERIODIC);
 624        mrp_pdu_queue(app);
 625        spin_unlock(&app->lock);
 626
 627        mrp_periodic_timer_arm(app);
 628}
 629
 630static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset)
 631{
 632        __be16 endmark;
 633
 634        if (skb_copy_bits(skb, *offset, &endmark, sizeof(endmark)) < 0)
 635                return -1;
 636        if (endmark == MRP_END_MARK) {
 637                *offset += sizeof(endmark);
 638                return -1;
 639        }
 640        return 0;
 641}
 642
 643static void mrp_pdu_parse_vecattr_event(struct mrp_applicant *app,
 644                                        struct sk_buff *skb,
 645                                        enum mrp_vecattr_event vaevent)
 646{
 647        struct mrp_attr *attr;
 648        enum mrp_event event;
 649
 650        attr = mrp_attr_lookup(app, mrp_cb(skb)->attrvalue,
 651                               mrp_cb(skb)->mh->attrlen,
 652                               mrp_cb(skb)->mh->attrtype);
 653        if (attr == NULL)
 654                return;
 655
 656        switch (vaevent) {
 657        case MRP_VECATTR_EVENT_NEW:
 658                event = MRP_EVENT_R_NEW;
 659                break;
 660        case MRP_VECATTR_EVENT_JOIN_IN:
 661                event = MRP_EVENT_R_JOIN_IN;
 662                break;
 663        case MRP_VECATTR_EVENT_IN:
 664                event = MRP_EVENT_R_IN;
 665                break;
 666        case MRP_VECATTR_EVENT_JOIN_MT:
 667                event = MRP_EVENT_R_JOIN_MT;
 668                break;
 669        case MRP_VECATTR_EVENT_MT:
 670                event = MRP_EVENT_R_MT;
 671                break;
 672        case MRP_VECATTR_EVENT_LV:
 673                event = MRP_EVENT_R_LV;
 674                break;
 675        default:
 676                return;
 677        }
 678
 679        mrp_attr_event(app, attr, event);
 680}
 681
 682static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
 683                                 struct sk_buff *skb, int *offset)
 684{
 685        struct mrp_vecattr_hdr _vah;
 686        u16 valen;
 687        u8 vaevents, vaevent;
 688
 689        mrp_cb(skb)->vah = skb_header_pointer(skb, *offset, sizeof(_vah),
 690                                              &_vah);
 691        if (!mrp_cb(skb)->vah)
 692                return -1;
 693        *offset += sizeof(_vah);
 694
 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);
 700
 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.
 706         */
 707        if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen >
 708            sizeof_field(struct sk_buff, cb))
 709                return -1;
 710        if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue,
 711                          mrp_cb(skb)->mh->attrlen) < 0)
 712                return -1;
 713        *offset += mrp_cb(skb)->mh->attrlen;
 714
 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.
 717         */
 718        while (valen > 0) {
 719                if (skb_copy_bits(skb, *offset, &vaevents,
 720                                  sizeof(vaevents)) < 0)
 721                        return -1;
 722                *offset += sizeof(vaevents);
 723
 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. */
 729                        return -1;
 730                }
 731                mrp_pdu_parse_vecattr_event(app, skb, vaevent);
 732
 733                /* If present, extract and process the second event. */
 734                if (!--valen)
 735                        break;
 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);
 742
 743                /* If present, extract and process the third event. */
 744                if (!--valen)
 745                        break;
 746                mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
 747                                  mrp_cb(skb)->mh->attrlen);
 748                vaevents %= __MRP_VECATTR_EVENT_MAX;
 749                vaevent = vaevents;
 750                mrp_pdu_parse_vecattr_event(app, skb, vaevent);
 751        }
 752        return 0;
 753}
 754
 755static int mrp_pdu_parse_msg(struct mrp_applicant *app, struct sk_buff *skb,
 756                             int *offset)
 757{
 758        struct mrp_msg_hdr _mh;
 759
 760        mrp_cb(skb)->mh = skb_header_pointer(skb, *offset, sizeof(_mh), &_mh);
 761        if (!mrp_cb(skb)->mh)
 762                return -1;
 763        *offset += sizeof(_mh);
 764
 765        if (mrp_cb(skb)->mh->attrtype == 0 ||
 766            mrp_cb(skb)->mh->attrtype > app->app->maxattr ||
 767            mrp_cb(skb)->mh->attrlen == 0)
 768                return -1;
 769
 770        while (skb->len > *offset) {
 771                if (mrp_pdu_parse_end_mark(skb, offset) < 0)
 772                        break;
 773                if (mrp_pdu_parse_vecattr(app, skb, offset) < 0)
 774                        return -1;
 775        }
 776        return 0;
 777}
 778
 779static int mrp_rcv(struct sk_buff *skb, struct net_device *dev,
 780                   struct packet_type *pt, struct net_device *orig_dev)
 781{
 782        struct mrp_application *appl = container_of(pt, struct mrp_application,
 783                                                    pkttype);
 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);
 789
 790        /* If the interface is in promiscuous mode, drop the packet if
 791         * it was unicast to another host.
 792         */
 793        if (unlikely(skb->pkt_type == PACKET_OTHERHOST))
 794                goto out;
 795        skb = skb_share_check(skb, GFP_ATOMIC);
 796        if (unlikely(!skb))
 797                goto out;
 798        port = rcu_dereference(dev->mrp_port);
 799        if (unlikely(!port))
 800                goto out;
 801        app = rcu_dereference(port->applicants[appl->type]);
 802        if (unlikely(!app))
 803                goto out;
 804
 805        ph = skb_header_pointer(skb, offset, sizeof(_ph), &_ph);
 806        if (!ph)
 807                goto out;
 808        offset += sizeof(_ph);
 809
 810        if (ph->version != app->app->version)
 811                goto out;
 812
 813        spin_lock(&app->lock);
 814        while (skb->len > offset) {
 815                if (mrp_pdu_parse_end_mark(skb, &offset) < 0)
 816                        break;
 817                if (mrp_pdu_parse_msg(app, skb, &offset) < 0)
 818                        break;
 819        }
 820        spin_unlock(&app->lock);
 821out:
 822        kfree_skb(skb);
 823        return 0;
 824}
 825
 826static int mrp_init_port(struct net_device *dev)
 827{
 828        struct mrp_port *port;
 829
 830        port = kzalloc(sizeof(*port), GFP_KERNEL);
 831        if (!port)
 832                return -ENOMEM;
 833        rcu_assign_pointer(dev->mrp_port, port);
 834        return 0;
 835}
 836
 837static void mrp_release_port(struct net_device *dev)
 838{
 839        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 840        unsigned int i;
 841
 842        for (i = 0; i <= MRP_APPLICATION_MAX; i++) {
 843                if (rtnl_dereference(port->applicants[i]))
 844                        return;
 845        }
 846        RCU_INIT_POINTER(dev->mrp_port, NULL);
 847        kfree_rcu(port, rcu);
 848}
 849
 850int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
 851{
 852        struct mrp_applicant *app;
 853        int err;
 854
 855        ASSERT_RTNL();
 856
 857        if (!rtnl_dereference(dev->mrp_port)) {
 858                err = mrp_init_port(dev);
 859                if (err < 0)
 860                        goto err1;
 861        }
 862
 863        err = -ENOMEM;
 864        app = kzalloc(sizeof(*app), GFP_KERNEL);
 865        if (!app)
 866                goto err2;
 867
 868        err = dev_mc_add(dev, appl->group_address);
 869        if (err < 0)
 870                goto err3;
 871
 872        app->dev = dev;
 873        app->app = appl;
 874        app->mad = RB_ROOT;
 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);
 882        return 0;
 883
 884err3:
 885        kfree(app);
 886err2:
 887        mrp_release_port(dev);
 888err1:
 889        return err;
 890}
 891EXPORT_SYMBOL_GPL(mrp_init_applicant);
 892
 893void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
 894{
 895        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 896        struct mrp_applicant *app = rtnl_dereference(
 897                port->applicants[appl->type]);
 898
 899        ASSERT_RTNL();
 900
 901        RCU_INIT_POINTER(port->applicants[appl->type], NULL);
 902
 903        /* Delete timer and generate a final TX event to flush out
 904         * all pending messages before the applicant is gone.
 905         */
 906        del_timer_sync(&app->join_timer);
 907        del_timer_sync(&app->periodic_timer);
 908
 909        spin_lock_bh(&app->lock);
 910        mrp_mad_event(app, MRP_EVENT_TX);
 911        mrp_attr_destroy_all(app);
 912        mrp_pdu_queue(app);
 913        spin_unlock_bh(&app->lock);
 914
 915        mrp_queue_xmit(app);
 916
 917        dev_mc_del(dev, appl->group_address);
 918        kfree_rcu(app, rcu);
 919        mrp_release_port(dev);
 920}
 921EXPORT_SYMBOL_GPL(mrp_uninit_applicant);
 922
 923int mrp_register_application(struct mrp_application *appl)
 924{
 925        appl->pkttype.func = mrp_rcv;
 926        dev_add_pack(&appl->pkttype);
 927        return 0;
 928}
 929EXPORT_SYMBOL_GPL(mrp_register_application);
 930
 931void mrp_unregister_application(struct mrp_application *appl)
 932{
 933        dev_remove_pack(&appl->pkttype);
 934}
 935EXPORT_SYMBOL_GPL(mrp_unregister_application);
 936