⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swconfig.c

📁 kernel mode code for configuring switches. can attach to phy abstraction layer. communicates with
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {		attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;		if (attr_id >= n_def)			goto done;		if (!test_bit(attr_id, def_active))			goto done;		attr = &def_list[attr_id];	} else {		if (attr_id >= alist->n_attr)			goto done;		attr = &alist->attr[attr_id];	}	if (attr->disabled)		attr = NULL;done:	if (!attr)		DPRINTF("attribute lookup failed\n");	val->attr = attr;	return attr;}static intswconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,		struct switch_val *val, int max){	struct nlattr *nla;	int rem;	val->len = 0;	nla_for_each_nested(nla, head, rem) {		struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];		struct switch_port *port = &val->value.ports[val->len];		if (val->len >= max)			return -EINVAL;		if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,				port_policy))			return -EINVAL;		if (!tb[SWITCH_PORT_ID])			return -EINVAL;		port->id = nla_get_u32(tb[SWITCH_PORT_ID]);		if (tb[SWITCH_PORT_FLAG_TAGGED])			port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED);		val->len++;	}	return 0;}static intswconfig_set_attr(struct sk_buff *skb, struct genl_info *info){	struct switch_attr *attr;	struct switch_dev *dev;	struct switch_val val;	int err = -EINVAL;	dev = swconfig_get_dev(info);	if (!dev)		return -EINVAL;	memset(&val, 0, sizeof(val));	attr = swconfig_lookup_attr(dev, info, &val);	if (!attr || !attr->set)		goto error;	val.attr = attr;	switch(attr->type) {	case SWITCH_TYPE_NOVAL:		break;	case SWITCH_TYPE_INT:		if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT])			goto error;		val.value.i =			nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]);		break;	case SWITCH_TYPE_STRING:		if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR])			goto error;		val.value.s =			nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]);		break;	case SWITCH_TYPE_PORTS:		val.value.ports = dev->portbuf;		memset(dev->portbuf, 0,			sizeof(struct switch_port) * dev->ports);		/* TODO: implement multipart? */		if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) {			err = swconfig_parse_ports(skb,				info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], &val, dev->ports);			if (err < 0)				goto error;		} else {			val.len = 0;			err = 0;		}		break;	default:		goto error;	}	err = attr->set(dev, attr, &val);error:	swconfig_put_dev(dev);	return err;}static intswconfig_close_portlist(struct swconfig_callback *cb, void *arg){	if (cb->nest[0])		nla_nest_end(cb->msg, cb->nest[0]);	return 0;}static intswconfig_send_port(struct swconfig_callback *cb, void *arg){	const struct switch_port *port = arg;	struct nlattr *p = NULL;	if (!cb->nest[0]) {		cb->nest[0] = nla_nest_start(cb->msg, cb->cmd);		if (!cb->nest[0])			return -1;	}	p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT);	if (!p)		goto error;	NLA_PUT_U32(cb->msg, SWITCH_PORT_ID, port->id);	if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))		NLA_PUT_FLAG(cb->msg, SWITCH_PORT_FLAG_TAGGED);	nla_nest_end(cb->msg, p);	return 0;nla_put_failure:		nla_nest_cancel(cb->msg, p);error:	nla_nest_cancel(cb->msg, cb->nest[0]);	return -1;}static intswconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr,		const struct switch_val *val){	struct swconfig_callback cb;	int err = 0;	int i;	if (!val->value.ports)		return -EINVAL;	memset(&cb, 0, sizeof(cb));	cb.cmd = attr;	cb.msg = *msg;	cb.info = info;	cb.fill = swconfig_send_port;	cb.close = swconfig_close_portlist;	cb.nest[0] = nla_nest_start(cb.msg, cb.cmd);	for (i = 0; i < val->len; i++) {		err = swconfig_send_multipart(&cb, &val->value.ports[i]);		if (err)			goto done;	}	err = val->len;	swconfig_close_portlist(&cb, NULL);	*msg = cb.msg;done:	return err;}static intswconfig_get_attr(struct sk_buff *skb, struct genl_info *info){	struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);	struct switch_attr *attr;	struct switch_dev *dev;	struct sk_buff *msg = NULL;	struct switch_val val;	int err = -EINVAL;	int cmd = hdr->cmd;	dev = swconfig_get_dev(info);	if (!dev)		return -EINVAL;	memset(&val, 0, sizeof(val));	attr = swconfig_lookup_attr(dev, info, &val);	if (!attr || !attr->get)		goto error_dev;	if (attr->type == SWITCH_TYPE_PORTS) {		val.value.ports = dev->portbuf;		memset(dev->portbuf, 0,			sizeof(struct switch_port) * dev->ports);	}	err = attr->get(dev, attr, &val);	if (err)		goto error;	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);	if (!msg)		goto error;	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,			0, cmd);	if (IS_ERR(hdr))		goto nla_put_failure;	switch(attr->type) {	case SWITCH_TYPE_INT:		NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i);		break;	case SWITCH_TYPE_STRING:		NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s);		break;	case SWITCH_TYPE_PORTS:		err = swconfig_send_ports(&msg, info,				SWITCH_ATTR_OP_VALUE_PORTS, &val);		if (err < 0)			goto nla_put_failure;		break;	default:		DPRINTF("invalid type in attribute\n");		err = -EINVAL;		goto error;	}	err = genlmsg_end(msg, hdr);	if (err < 0)		goto nla_put_failure;	swconfig_put_dev(dev);	return genlmsg_unicast(msg, info->snd_pid);nla_put_failure:	if (msg)		nlmsg_free(msg);error_dev:	swconfig_put_dev(dev);error:	if (!err)		err = -ENOMEM;	return err;}static intswconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags,		const struct switch_dev *dev){	void *hdr;	hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags,			SWITCH_CMD_NEW_ATTR);	if (IS_ERR(hdr))		return -1;	NLA_PUT_U32(msg, SWITCH_ATTR_ID, dev->id);	NLA_PUT_STRING(msg, SWITCH_ATTR_NAME, dev->name);	NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);	NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);	NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);	return genlmsg_end(msg, hdr);nla_put_failure:	genlmsg_cancel(msg, hdr);	return -EMSGSIZE;}static int swconfig_dump_switches(struct sk_buff *skb,		struct netlink_callback *cb){	struct switch_dev *dev;	int start = cb->args[0];	int idx = 0;	swconfig_lock();	list_for_each_entry(dev, &swdevs, dev_list) {		if (++idx <= start)			continue;		if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).pid,				cb->nlh->nlmsg_seq, NLM_F_MULTI,				dev) < 0)			break;	}	swconfig_unlock();	cb->args[0] = idx;	return skb->len;}static intswconfig_done(struct netlink_callback *cb){	return 0;}static struct genl_ops swconfig_ops[] = {	{		.cmd = SWITCH_CMD_LIST_GLOBAL,		.doit = swconfig_list_attrs,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_LIST_VLAN,		.doit = swconfig_list_attrs,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_LIST_PORT,		.doit = swconfig_list_attrs,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_GET_GLOBAL,		.doit = swconfig_get_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_GET_VLAN,		.doit = swconfig_get_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_GET_PORT,		.doit = swconfig_get_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_SET_GLOBAL,		.doit = swconfig_set_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_SET_VLAN,		.doit = swconfig_set_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_SET_PORT,		.doit = swconfig_set_attr,		.policy = switch_policy,	},	{		.cmd = SWITCH_CMD_GET_SWITCH,		.dumpit = swconfig_dump_switches,		.policy = switch_policy,		.done = swconfig_done,	}};intregister_switch(struct switch_dev *dev, struct net_device *netdev){	INIT_LIST_HEAD(&dev->dev_list);	if (netdev) {		dev->netdev = netdev;		if (!dev->devname)			dev->devname = netdev->name;	}	BUG_ON(!dev->devname);	if (dev->ports > 0) {		dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,				GFP_KERNEL);		if (!dev->portbuf)			return -ENOMEM;	}	dev->id = ++swdev_id;	swconfig_defaults_init(dev);	spin_lock_init(&dev->lock);	swconfig_lock();	list_add(&dev->dev_list, &swdevs);	swconfig_unlock();	return 0;}EXPORT_SYMBOL_GPL(register_switch);voidunregister_switch(struct switch_dev *dev){	kfree(dev->portbuf);	spin_lock(&dev->lock);	swconfig_lock();	list_del(&dev->dev_list);	swconfig_unlock();}EXPORT_SYMBOL_GPL(unregister_switch);static int __initswconfig_init(void){	int i, err;	INIT_LIST_HEAD(&swdevs);	err = genl_register_family(&switch_fam);	if (err)		return err;	for (i = 0; i < ARRAY_SIZE(swconfig_ops); i++) {		err = genl_register_ops(&switch_fam, &swconfig_ops[i]);		if (err)			goto unregister;	}	return 0;unregister:	genl_unregister_family(&switch_fam);	return err;}static void __exitswconfig_exit(void){	genl_unregister_family(&switch_fam);}module_init(swconfig_init);module_exit(swconfig_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -