cregit-Linux how code gets into the kernel

Release 4.11 net/802/mrp.c

Directory: net/802
/*
 *      IEEE 802.1Q Multiple Registration Protocol (MRP)
 *
 *      Copyright (c) 2012 Massachusetts Institute of Technology
 *
 *      Adapted from code in net/802/garp.c
 *      Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      version 2 as published by the Free Software Foundation.
 */
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <net/mrp.h>
#include <asm/unaligned.h>


static unsigned int mrp_join_time __read_mostly = 200;
module_param(mrp_join_time, uint, 0644);
MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");


static unsigned int mrp_periodic_time __read_mostly = 1000;
module_param(mrp_periodic_time, uint, 0644);
MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)");

MODULE_LICENSE("GPL");

static const u8

mrp_applicant_state_table[MRP_APPLICANT_MAX + 1][MRP_EVENT_MAX + 1] = {
	[MRP_APPLICANT_VO] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_VO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_VO,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VO,
        },
	[MRP_APPLICANT_VP] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_VO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_AA,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VP,
        },
	[MRP_APPLICANT_VN] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VN,
		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
		[MRP_EVENT_TX]		= MRP_APPLICANT_AN,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VN,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VN,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VN,
        },
	[MRP_APPLICANT_AN] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_AN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AN,
		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AN,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AN,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AN,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AN,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AN,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VN,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VN,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VN,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AN,
        },
	[MRP_APPLICANT_AA] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AA,
		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QA,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AA,
        },
	[MRP_APPLICANT_QA] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QA,
		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QA,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QA,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QA,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AA,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AA,
        },
	[MRP_APPLICANT_LA] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AA,
		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
		[MRP_EVENT_TX]		= MRP_APPLICANT_VO,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_LA,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_LA,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_LA,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_LA,
        },
	[MRP_APPLICANT_AO] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_AO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_AO,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QO,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AO,
        },
	[MRP_APPLICANT_QO] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_QO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QO,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QO,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QO,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QO,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AO,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_QO,
        },
	[MRP_APPLICANT_AP] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_AO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QP,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AP,
        },
	[MRP_APPLICANT_QP] = {
		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QP,
		[MRP_EVENT_LV]		= MRP_APPLICANT_QO,
		[MRP_EVENT_TX]		= MRP_APPLICANT_QP,
		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QP,
		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QP,
		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QP,
		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AP,
		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AP,
        },
};

static const u8

mrp_tx_action_table[MRP_APPLICANT_MAX + 1] = {
	[MRP_APPLICANT_VO] = MRP_TX_ACTION_S_IN_OPTIONAL,
	[MRP_APPLICANT_VP] = MRP_TX_ACTION_S_JOIN_IN,
	[MRP_APPLICANT_VN] = MRP_TX_ACTION_S_NEW,
	[MRP_APPLICANT_AN] = MRP_TX_ACTION_S_NEW,
	[MRP_APPLICANT_AA] = MRP_TX_ACTION_S_JOIN_IN,
	[MRP_APPLICANT_QA] = MRP_TX_ACTION_S_JOIN_IN_OPTIONAL,
	[MRP_APPLICANT_LA] = MRP_TX_ACTION_S_LV,
	[MRP_APPLICANT_AO] = MRP_TX_ACTION_S_IN_OPTIONAL,
	[MRP_APPLICANT_QO] = MRP_TX_ACTION_S_IN_OPTIONAL,
	[MRP_APPLICANT_AP] = MRP_TX_ACTION_S_JOIN_IN,
	[MRP_APPLICANT_QP] = MRP_TX_ACTION_S_IN_OPTIONAL,
};


static void mrp_attrvalue_inc(void *value, u8 len) { u8 *v = (u8 *)value; /* Add 1 to the last byte. If it becomes zero, * go to the previous byte and repeat. */ while (len > 0 && !++v[--len]) ; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward39100.00%1100.00%
Total39100.00%1100.00%


static int mrp_attr_cmp(const struct mrp_attr *attr, const void *value, u8 len, u8 type) { if (attr->type != type) return attr->type - type; if (attr->len != len) return attr->len - len; return memcmp(attr->value, value, len); }

Contributors

PersonTokensPropCommitsCommitProp
David Ward65100.00%1100.00%
Total65100.00%1100.00%


static struct mrp_attr *mrp_attr_lookup(const struct mrp_applicant *app, const void *value, u8 len, u8 type) { struct rb_node *parent = app->mad.rb_node; struct mrp_attr *attr; int d; while (parent) { attr = rb_entry(parent, struct mrp_attr, node); d = mrp_attr_cmp(attr, value, len, type); if (d > 0) parent = parent->rb_left; else if (d < 0) parent = parent->rb_right; else return attr; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward107100.00%1100.00%
Total107100.00%1100.00%


static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app, const void *value, u8 len, u8 type) { struct rb_node *parent = NULL, **p = &app->mad.rb_node; struct mrp_attr *attr; int d; while (*p) { parent = *p; attr = rb_entry(parent, struct mrp_attr, node); d = mrp_attr_cmp(attr, value, len, type); if (d > 0) p = &parent->rb_left; else if (d < 0) p = &parent->rb_right; else { /* The attribute already exists; re-use it. */ return attr; } } attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC); if (!attr) return attr; attr->state = MRP_APPLICANT_VO; attr->type = type; attr->len = len; memcpy(attr->value, value, len); rb_link_node(&attr->node, parent, p); rb_insert_color(&attr->node, &app->mad); return attr; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward201100.00%1100.00%
Total201100.00%1100.00%


static void mrp_attr_destroy(struct mrp_applicant *app, struct mrp_attr *attr) { rb_erase(&attr->node, &app->mad); kfree(attr); }

Contributors

PersonTokensPropCommitsCommitProp
David Ward34100.00%1100.00%
Total34100.00%1100.00%


static int mrp_pdu_init(struct mrp_applicant *app) { struct sk_buff *skb; struct mrp_pdu_hdr *ph; skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev), GFP_ATOMIC); if (!skb) return -ENOMEM; skb->dev = app->dev; skb->protocol = app->app->pkttype.type; skb_reserve(skb, LL_RESERVED_SPACE(app->dev)); skb_reset_network_header(skb); skb_reset_transport_header(skb); ph = (struct mrp_pdu_hdr *)__skb_put(skb, sizeof(*ph)); ph->version = app->app->version; app->pdu = skb; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward129100.00%1100.00%
Total129100.00%1100.00%


static int mrp_pdu_append_end_mark(struct mrp_applicant *app) { __be16 *endmark; if (skb_tailroom(app->pdu) < sizeof(*endmark)) return -1; endmark = (__be16 *)__skb_put(app->pdu, sizeof(*endmark)); put_unaligned(MRP_END_MARK, endmark); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward63100.00%1100.00%
Total63100.00%1100.00%


static void mrp_pdu_queue(struct mrp_applicant *app) { if (!app->pdu) return; if (mrp_cb(app->pdu)->mh) mrp_pdu_append_end_mark(app); mrp_pdu_append_end_mark(app); dev_hard_header(app->pdu, app->dev, ntohs(app->app->pkttype.type), app->app->group_address, app->dev->dev_addr, app->pdu->len); skb_queue_tail(&app->queue, app->pdu); app->pdu = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward98100.00%1100.00%
Total98100.00%1100.00%


static void mrp_queue_xmit(struct mrp_applicant *app) { struct sk_buff *skb; while ((skb = skb_dequeue(&app->queue))) dev_queue_xmit(skb); }

Contributors

PersonTokensPropCommitsCommitProp
David Ward35100.00%1100.00%
Total35100.00%1100.00%


static int mrp_pdu_append_msg_hdr(struct mrp_applicant *app, u8 attrtype, u8 attrlen) { struct mrp_msg_hdr *mh; if (mrp_cb(app->pdu)->mh) { if (mrp_pdu_append_end_mark(app) < 0) return -1; mrp_cb(app->pdu)->mh = NULL; mrp_cb(app->pdu)->vah = NULL; } if (skb_tailroom(app->pdu) < sizeof(*mh)) return -1; mh = (struct mrp_msg_hdr *)__skb_put(app->pdu, sizeof(*mh)); mh->attrtype = attrtype; mh->attrlen = attrlen; mrp_cb(app->pdu)->mh = mh; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward135100.00%1100.00%
Total135100.00%1100.00%


static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant *app, const void *firstattrvalue, u8 attrlen) { struct mrp_vecattr_hdr *vah; if (skb_tailroom(app->pdu) < sizeof(*vah) + attrlen) return -1; vah = (struct mrp_vecattr_hdr *)__skb_put(app->pdu, sizeof(*vah) + attrlen); put_unaligned(0, &vah->lenflags); memcpy(vah->firstattrvalue, firstattrvalue, attrlen); mrp_cb(app->pdu)->vah = vah; memcpy(mrp_cb(app->pdu)->attrvalue, firstattrvalue, attrlen); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward118100.00%1100.00%
Total118100.00%1100.00%


static int mrp_pdu_append_vecattr_event(struct mrp_applicant *app, const struct mrp_attr *attr, enum mrp_vecattr_event vaevent) { u16 len, pos; u8 *vaevents; int err; again: if (!app->pdu) { err = mrp_pdu_init(app); if (err < 0) return err; } /* If there is no Message header in the PDU, or the Message header is * for a different attribute type, add an EndMark (if necessary) and a * new Message header to the PDU. */ if (!mrp_cb(app->pdu)->mh || mrp_cb(app->pdu)->mh->attrtype != attr->type || mrp_cb(app->pdu)->mh->attrlen != attr->len) { if (mrp_pdu_append_msg_hdr(app, attr->type, attr->len) < 0) goto queue; } /* If there is no VectorAttribute header for this Message in the PDU, * or this attribute's value does not sequentially follow the previous * attribute's value, add a new VectorAttribute header to the PDU. */ if (!mrp_cb(app->pdu)->vah || memcmp(mrp_cb(app->pdu)->attrvalue, attr->value, attr->len)) { if (mrp_pdu_append_vecattr_hdr(app, attr->value, attr->len) < 0) goto queue; } len = be16_to_cpu(get_unaligned(&mrp_cb(app->pdu)->vah->lenflags)); pos = len % 3; /* Events are packed into Vectors in the PDU, three to a byte. Add a * byte to the end of the Vector if necessary. */ if (!pos) { if (skb_tailroom(app->pdu) < sizeof(u8)) goto queue; vaevents = (u8 *)__skb_put(app->pdu, sizeof(u8)); } else { vaevents = (u8 *)(skb_tail_pointer(app->pdu) - sizeof(u8)); } switch (pos) { case 0: *vaevents = vaevent * (__MRP_VECATTR_EVENT_MAX * __MRP_VECATTR_EVENT_MAX); break; case 1: *vaevents += vaevent * __MRP_VECATTR_EVENT_MAX; break; case 2: *vaevents += vaevent; break; default: WARN_ON(1); } /* Increment the length of the VectorAttribute in the PDU, as well as * the value of the next attribute that would continue its Vector. */ put_unaligned(cpu_to_be16(++len), &mrp_cb(app->pdu)->vah->lenflags); mrp_attrvalue_inc(mrp_cb(app->pdu)->attrvalue, attr->len); return 0; queue: mrp_pdu_queue(app); goto again; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward370100.00%1100.00%
Total370100.00%1100.00%


static void mrp_attr_event(struct mrp_applicant *app, struct mrp_attr *attr, enum mrp_event event) { enum mrp_applicant_state state; state = mrp_applicant_state_table[attr->state][event]; if (state == MRP_APPLICANT_INVALID) { WARN_ON(1); return; } if (event == MRP_EVENT_TX) { /* When appending the attribute fails, don't update its state * in order to retry at the next TX event. */ switch (mrp_tx_action_table[attr->state]) { case MRP_TX_ACTION_NONE: case MRP_TX_ACTION_S_JOIN_IN_OPTIONAL: case MRP_TX_ACTION_S_IN_OPTIONAL: break; case MRP_TX_ACTION_S_NEW: if (mrp_pdu_append_vecattr_event( app, attr, MRP_VECATTR_EVENT_NEW) < 0) return; break; case MRP_TX_ACTION_S_JOIN_IN: if (mrp_pdu_append_vecattr_event( app, attr, MRP_VECATTR_EVENT_JOIN_IN) < 0) return; break; case MRP_TX_ACTION_S_LV: if (mrp_pdu_append_vecattr_event( app, attr, MRP_VECATTR_EVENT_LV) < 0) return; /* As a pure applicant, sending a leave message * implies that the attribute was unregistered and * can be destroyed. */ mrp_attr_destroy(app, attr); return; default: WARN_ON(1); } } attr->state = state; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward154100.00%1100.00%
Total154100.00%1100.00%


int mrp_request_join(const struct net_device *dev, const struct mrp_application *appl, const void *value, u8 len, u8 type) { struct mrp_port *port = rtnl_dereference(dev->mrp_port); struct mrp_applicant *app = rtnl_dereference( port->applicants[appl->type]); struct mrp_attr *attr; if (sizeof(struct mrp_skb_cb) + len > FIELD_SIZEOF(struct sk_buff, cb)) return -ENOMEM; spin_lock_bh(&app->lock); attr = mrp_attr_create(app, value, len, type); if (!attr) { spin_unlock_bh(&app->lock); return -ENOMEM; } mrp_attr_event(app, attr, MRP_EVENT_JOIN); spin_unlock_bh(&app->lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Ward144100.00%1100.00%
Total144100.00%1100.00%

EXPORT_SYMBOL_GPL(mrp_request_join);
void mrp_request_leave(const struct net_device *dev, const struct mrp_application *appl, const void *value, u8 len, u8 type) { struct mrp_port *port = rtnl_dereference(dev->mrp_port); struct mrp_applicant *app = rtnl_dereference( port->applicants[appl->type]); struct mrp_attr *attr; if (sizeof(struct mrp_skb_cb) + len > FIELD_SIZEOF(struct sk_buff, cb)) return; spin_lock_bh(&app->lock); attr = mrp_attr_lookup(app, value, len, type); if (!attr) { spin_unlock_bh(&app->lock); return; } mrp_attr_event(app, attr, MRP_EVENT_LV); spin_unlock_bh(&app->lock); }

Contributors

PersonTokensPropCommitsCommitProp
David Ward135100.00%1100.00%
Total135100.00%1100.00%

EXPORT_SYMBOL_GPL(mrp_request_leave);
static void mrp_mad_event(struct mrp_applicant *app, enum mrp_event event) { struct rb_node *node, *next; struct mrp_attr *attr; for (node = rb_first(&app->mad); next = node ? rb_next(node) : NULL, node != NULL; node = next) { attr