2 * Copyright (c) 2007-2012 Nicira Networks.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <linux/kernel.h>
20 #include <linux/jhash.h>
21 #include <linux/list.h>
22 #include <linux/rtnetlink.h>
23 #include <net/net_namespace.h>
28 #include "vport-generic.h"
33 char peer_name[IFNAMSIZ];
34 unsigned char eth_addr[ETH_ALEN];
42 /* Protected by RTNL lock. */
43 struct hlist_node hash_node;
45 struct vport __rcu *peer;
46 struct patch_config __rcu *patchconf;
49 /* Protected by RTNL lock. */
50 static struct hlist_head *peer_table;
51 #define PEER_HASH_BUCKETS 256
53 static void update_peers(struct net *, const char *name, struct vport *);
55 static struct patch_vport *patch_vport_priv(const struct vport *vport)
57 return vport_priv(vport);
61 static void free_config(struct rcu_head *rcu)
63 struct patch_config *c = container_of(rcu, struct patch_config, rcu);
67 static void assign_config_rcu(struct vport *vport,
68 struct patch_config *new_config)
70 struct patch_vport *patch_vport = patch_vport_priv(vport);
71 struct patch_config *old_config;
73 old_config = rtnl_dereference(patch_vport->patchconf);
74 rcu_assign_pointer(patch_vport->patchconf, new_config);
75 call_rcu(&old_config->rcu, free_config);
78 static struct hlist_head *hash_bucket(struct net *net, const char *name)
80 unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
81 return &peer_table[hash & (PEER_HASH_BUCKETS - 1)];
84 static int patch_init(void)
86 peer_table = kzalloc(PEER_HASH_BUCKETS * sizeof(struct hlist_head),
94 static void patch_exit(void)
99 static const struct nla_policy patch_policy[OVS_PATCH_ATTR_MAX + 1] = {
100 #ifdef HAVE_NLA_NUL_STRING
101 [OVS_PATCH_ATTR_PEER] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
105 static int patch_set_config(struct vport *vport, const struct nlattr *options,
106 struct patch_config *patchconf)
108 struct patch_vport *patch_vport = patch_vport_priv(vport);
109 struct nlattr *a[OVS_PATCH_ATTR_MAX + 1];
110 const char *peer_name;
116 err = nla_parse_nested(a, OVS_PATCH_ATTR_MAX, options, patch_policy);
120 if (!a[OVS_PATCH_ATTR_PEER] ||
121 CHECK_NUL_STRING(a[OVS_PATCH_ATTR_PEER], IFNAMSIZ - 1))
124 peer_name = nla_data(a[OVS_PATCH_ATTR_PEER]);
125 if (!strcmp(patch_vport->name, peer_name))
128 strcpy(patchconf->peer_name, peer_name);
133 static struct vport *patch_create(const struct vport_parms *parms)
136 struct patch_vport *patch_vport;
137 const char *peer_name;
138 struct patch_config *patchconf;
139 struct net *net = ovs_dp_get_net(parms->dp);
142 vport = ovs_vport_alloc(sizeof(struct patch_vport),
143 &ovs_patch_vport_ops, parms);
145 err = PTR_ERR(vport);
149 patch_vport = patch_vport_priv(vport);
151 strcpy(patch_vport->name, parms->name);
153 patchconf = kmalloc(sizeof(struct patch_config), GFP_KERNEL);
156 goto error_free_vport;
159 err = patch_set_config(vport, parms->options, patchconf);
161 goto error_free_patchconf;
163 random_ether_addr(patchconf->eth_addr);
165 rcu_assign_pointer(patch_vport->patchconf, patchconf);
167 peer_name = patchconf->peer_name;
168 hlist_add_head(&patch_vport->hash_node, hash_bucket(net, peer_name));
169 rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(net, peer_name));
170 update_peers(net, patch_vport->name, vport);
174 error_free_patchconf:
177 ovs_vport_free(vport);
182 static void free_port_rcu(struct rcu_head *rcu)
184 struct patch_vport *patch_vport = container_of(rcu,
185 struct patch_vport, rcu);
187 kfree((struct patch_config __force *)patch_vport->patchconf);
188 ovs_vport_free(vport_from_priv(patch_vport));
191 static void patch_destroy(struct vport *vport)
193 struct patch_vport *patch_vport = patch_vport_priv(vport);
195 update_peers(ovs_dp_get_net(vport->dp), patch_vport->name, NULL);
196 hlist_del(&patch_vport->hash_node);
197 call_rcu(&patch_vport->rcu, free_port_rcu);
200 static int patch_set_options(struct vport *vport, struct nlattr *options)
202 struct patch_vport *patch_vport = patch_vport_priv(vport);
203 struct patch_config *patchconf;
206 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
207 sizeof(struct patch_config), GFP_KERNEL);
213 err = patch_set_config(vport, options, patchconf);
217 assign_config_rcu(vport, patchconf);
219 hlist_del(&patch_vport->hash_node);
221 rcu_assign_pointer(patch_vport->peer,
222 ovs_vport_locate(ovs_dp_get_net(vport->dp), patchconf->peer_name));
224 hlist_add_head(&patch_vport->hash_node,
225 hash_bucket(ovs_dp_get_net(vport->dp), patchconf->peer_name));
234 static void update_peers(struct net *net, const char *name, struct vport *vport)
236 struct hlist_head *bucket = hash_bucket(ovs_dp_get_net(vport->dp), name);
237 struct patch_vport *peer_vport;
238 struct hlist_node *node;
240 hlist_for_each_entry(peer_vport, node, bucket, hash_node) {
241 struct vport *curr_vport = vport_from_priv(peer_vport);
242 const char *peer_name;
244 peer_name = rtnl_dereference(peer_vport->patchconf)->peer_name;
245 if (!strcmp(peer_name, name) && net_eq(ovs_dp_get_net(curr_vport->dp), net))
246 rcu_assign_pointer(peer_vport->peer, vport);
250 static int patch_set_addr(struct vport *vport, const unsigned char *addr)
252 struct patch_vport *patch_vport = patch_vport_priv(vport);
253 struct patch_config *patchconf;
255 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
256 sizeof(struct patch_config), GFP_KERNEL);
260 memcpy(patchconf->eth_addr, addr, ETH_ALEN);
261 assign_config_rcu(vport, patchconf);
267 static const char *patch_get_name(const struct vport *vport)
269 const struct patch_vport *patch_vport = patch_vport_priv(vport);
270 return patch_vport->name;
273 static const unsigned char *patch_get_addr(const struct vport *vport)
275 const struct patch_vport *patch_vport = patch_vport_priv(vport);
276 return rcu_dereference_rtnl(patch_vport->patchconf)->eth_addr;
279 static int patch_get_options(const struct vport *vport, struct sk_buff *skb)
281 struct patch_vport *patch_vport = patch_vport_priv(vport);
282 struct patch_config *patchconf = rcu_dereference_rtnl(patch_vport->patchconf);
284 return nla_put_string(skb, OVS_PATCH_ATTR_PEER, patchconf->peer_name);
287 static int patch_send(struct vport *vport, struct sk_buff *skb)
289 struct patch_vport *patch_vport = patch_vport_priv(vport);
290 struct vport *peer = rcu_dereference(patch_vport->peer);
291 int skb_len = skb->len;
295 ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
300 ovs_vport_receive(peer, skb);
304 const struct vport_ops ovs_patch_vport_ops = {
305 .type = OVS_VPORT_TYPE_PATCH,
308 .create = patch_create,
309 .destroy = patch_destroy,
310 .set_addr = patch_set_addr,
311 .get_name = patch_get_name,
312 .get_addr = patch_get_addr,
313 .get_options = patch_get_options,
314 .set_options = patch_set_options,
315 .get_dev_flags = ovs_vport_gen_get_dev_flags,
316 .is_running = ovs_vport_gen_is_running,
317 .get_operstate = ovs_vport_gen_get_operstate,