diff options
| author | Pavel Emelianov <xemul@openvz.org> | 2007-08-09 01:16:38 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:47:45 -0400 |
| commit | e71992889ee289a87f6641cfa40d64a5699bcb53 (patch) | |
| tree | d078d6a4d98348518229ad12ad3ecc847680c884 | |
| parent | bea3348eef27e6044b6161fd04c3152215f96411 (diff) | |
[RTNETLINK]: Introduce generic rtnl_create_link().
This routine gets the parsed rtnl attributes and creates a new
link with generic info (IFLA_LINKINFO policy). Its intention
is to help the drivers, that need to create several links at
once (like VETH).
This is nothing but a copy-paste-ed part of rtnl_newlink() function
that is responsible for creation of new device.
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/rtnetlink.h | 4 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 83 |
2 files changed, 57 insertions, 30 deletions
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 3861c05cdf0f..8218288ab7ee 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h | |||
| @@ -78,6 +78,10 @@ extern void __rtnl_link_unregister(struct rtnl_link_ops *ops); | |||
| 78 | extern int rtnl_link_register(struct rtnl_link_ops *ops); | 78 | extern int rtnl_link_register(struct rtnl_link_ops *ops); |
| 79 | extern void rtnl_link_unregister(struct rtnl_link_ops *ops); | 79 | extern void rtnl_link_unregister(struct rtnl_link_ops *ops); |
| 80 | 80 | ||
| 81 | extern struct net_device *rtnl_create_link(char *ifname, | ||
| 82 | const struct rtnl_link_ops *ops, struct nlattr *tb[]); | ||
| 83 | extern const struct nla_policy ifla_policy[IFLA_MAX+1]; | ||
| 84 | |||
| 81 | #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) | 85 | #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) |
| 82 | 86 | ||
| 83 | #endif | 87 | #endif |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 2b0b6fac6cef..dca9e80ba574 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -713,7 +713,7 @@ cont: | |||
| 713 | return skb->len; | 713 | return skb->len; |
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | 716 | const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
| 717 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 717 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
| 718 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 718 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
| 719 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 719 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
| @@ -937,6 +937,48 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 937 | return 0; | 937 | return 0; |
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | struct net_device *rtnl_create_link(char *ifname, | ||
| 941 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | ||
| 942 | { | ||
| 943 | int err; | ||
| 944 | struct net_device *dev; | ||
| 945 | |||
| 946 | err = -ENOMEM; | ||
| 947 | dev = alloc_netdev(ops->priv_size, ifname, ops->setup); | ||
| 948 | if (!dev) | ||
| 949 | goto err; | ||
| 950 | |||
| 951 | if (strchr(dev->name, '%')) { | ||
| 952 | err = dev_alloc_name(dev, dev->name); | ||
| 953 | if (err < 0) | ||
| 954 | goto err_free; | ||
| 955 | } | ||
| 956 | |||
| 957 | dev->rtnl_link_ops = ops; | ||
| 958 | |||
| 959 | if (tb[IFLA_MTU]) | ||
| 960 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | ||
| 961 | if (tb[IFLA_ADDRESS]) | ||
| 962 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), | ||
| 963 | nla_len(tb[IFLA_ADDRESS])); | ||
| 964 | if (tb[IFLA_BROADCAST]) | ||
| 965 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), | ||
| 966 | nla_len(tb[IFLA_BROADCAST])); | ||
| 967 | if (tb[IFLA_TXQLEN]) | ||
| 968 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | ||
| 969 | if (tb[IFLA_OPERSTATE]) | ||
| 970 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | ||
| 971 | if (tb[IFLA_LINKMODE]) | ||
| 972 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | ||
| 973 | |||
| 974 | return dev; | ||
| 975 | |||
| 976 | err_free: | ||
| 977 | free_netdev(dev); | ||
| 978 | err: | ||
| 979 | return ERR_PTR(err); | ||
| 980 | } | ||
| 981 | |||
| 940 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 982 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 941 | { | 983 | { |
| 942 | const struct rtnl_link_ops *ops; | 984 | const struct rtnl_link_ops *ops; |
| @@ -1049,38 +1091,17 @@ replay: | |||
| 1049 | 1091 | ||
| 1050 | if (!ifname[0]) | 1092 | if (!ifname[0]) |
| 1051 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 1093 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
| 1052 | dev = alloc_netdev(ops->priv_size, ifname, ops->setup); | 1094 | |
| 1053 | if (!dev) | 1095 | dev = rtnl_create_link(ifname, ops, tb); |
| 1054 | return -ENOMEM; | 1096 | |
| 1055 | 1097 | if (IS_ERR(dev)) | |
| 1056 | if (strchr(dev->name, '%')) { | 1098 | err = PTR_ERR(dev); |
| 1057 | err = dev_alloc_name(dev, dev->name); | 1099 | else if (ops->newlink) |
| 1058 | if (err < 0) | ||
| 1059 | goto err_free; | ||
| 1060 | } | ||
| 1061 | dev->rtnl_link_ops = ops; | ||
| 1062 | |||
| 1063 | if (tb[IFLA_MTU]) | ||
| 1064 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | ||
| 1065 | if (tb[IFLA_ADDRESS]) | ||
| 1066 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), | ||
| 1067 | nla_len(tb[IFLA_ADDRESS])); | ||
| 1068 | if (tb[IFLA_BROADCAST]) | ||
| 1069 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), | ||
| 1070 | nla_len(tb[IFLA_BROADCAST])); | ||
| 1071 | if (tb[IFLA_TXQLEN]) | ||
| 1072 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | ||
| 1073 | if (tb[IFLA_OPERSTATE]) | ||
| 1074 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | ||
| 1075 | if (tb[IFLA_LINKMODE]) | ||
| 1076 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | ||
| 1077 | |||
| 1078 | if (ops->newlink) | ||
| 1079 | err = ops->newlink(dev, tb, data); | 1100 | err = ops->newlink(dev, tb, data); |
| 1080 | else | 1101 | else |
| 1081 | err = register_netdevice(dev); | 1102 | err = register_netdevice(dev); |
| 1082 | err_free: | 1103 | |
| 1083 | if (err < 0) | 1104 | if (err < 0 && !IS_ERR(dev)) |
| 1084 | free_netdev(dev); | 1105 | free_netdev(dev); |
| 1085 | return err; | 1106 | return err; |
| 1086 | } | 1107 | } |
| @@ -1329,3 +1350,5 @@ EXPORT_SYMBOL(rtnl_unlock); | |||
| 1329 | EXPORT_SYMBOL(rtnl_unicast); | 1350 | EXPORT_SYMBOL(rtnl_unicast); |
| 1330 | EXPORT_SYMBOL(rtnl_notify); | 1351 | EXPORT_SYMBOL(rtnl_notify); |
| 1331 | EXPORT_SYMBOL(rtnl_set_sk_err); | 1352 | EXPORT_SYMBOL(rtnl_set_sk_err); |
| 1353 | EXPORT_SYMBOL(rtnl_create_link); | ||
| 1354 | EXPORT_SYMBOL(ifla_policy); | ||
