2 * Copyright (c) 2007-2011 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/dcache.h>
20 #include <linux/kernel.h>
21 #include <linux/list.h>
22 #include <linux/rtnetlink.h>
27 #include "vport-generic.h"
32 char peer_name[IFNAMSIZ];
33 unsigned char eth_addr[ETH_ALEN];
41 /* Protected by RTNL lock. */
42 struct hlist_node hash_node;
44 struct vport __rcu *peer;
45 struct patch_config __rcu *patchconf;
48 /* Protected by RTNL lock. */
49 static struct hlist_head *peer_table;
50 #define PEER_HASH_BUCKETS 256
52 static void update_peers(const char *name, struct vport *);
54 static struct patch_vport *patch_vport_priv(const struct vport *vport)
56 return vport_priv(vport);
60 static void free_config(struct rcu_head *rcu)
62 struct patch_config *c = container_of(rcu, struct patch_config, rcu);
66 static void assign_config_rcu(struct vport *vport,
67 struct patch_config *new_config)
69 struct patch_vport *patch_vport = patch_vport_priv(vport);
70 struct patch_config *old_config;
72 old_config = rtnl_dereference(patch_vport->patchconf);
73 rcu_assign_pointer(patch_vport->patchconf, new_config);
74 call_rcu(&old_config->rcu, free_config);
77 static struct hlist_head *hash_bucket(const char *name)
79 unsigned int hash = full_name_hash(name, strlen(name));
80 return &peer_table[hash & (PEER_HASH_BUCKETS - 1)];
83 static int patch_init(void)
85 peer_table = kzalloc(PEER_HASH_BUCKETS * sizeof(struct hlist_head),
93 static void patch_exit(void)
98 static const struct nla_policy patch_policy[OVS_PATCH_ATTR_MAX + 1] = {
99 #ifdef HAVE_NLA_NUL_STRING
100 [OVS_PATCH_ATTR_PEER] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
104 static int patch_set_config(struct vport *vport, const struct nlattr *options,
105 struct patch_config *patchconf)
107 struct patch_vport *patch_vport = patch_vport_priv(vport);
108 struct nlattr *a[OVS_PATCH_ATTR_MAX + 1];
109 const char *peer_name;
115 err = nla_parse_nested(a, OVS_PATCH_ATTR_MAX, options, patch_policy);
119 if (!a[OVS_PATCH_ATTR_PEER] ||
120 CHECK_NUL_STRING(a[OVS_PATCH_ATTR_PEER], IFNAMSIZ - 1))
123 peer_name = nla_data(a[OVS_PATCH_ATTR_PEER]);
124 if (!strcmp(patch_vport->name, peer_name))
127 strcpy(patchconf->peer_name, peer_name);
132 static struct vport *patch_create(const struct vport_parms *parms)
135 struct patch_vport *patch_vport;
136 const char *peer_name;
137 struct patch_config *patchconf;
140 vport = ovs_vport_alloc(sizeof(struct patch_vport),
141 &ovs_patch_vport_ops, parms);
143 err = PTR_ERR(vport);
147 patch_vport = patch_vport_priv(vport);
149 strcpy(patch_vport->name, parms->name);
151 patchconf = kmalloc(sizeof(struct patch_config), GFP_KERNEL);
154 goto error_free_vport;
157 err = patch_set_config(vport, parms->options, patchconf);
159 goto error_free_patchconf;
161 random_ether_addr(patchconf->eth_addr);
163 rcu_assign_pointer(patch_vport->patchconf, patchconf);
165 peer_name = patchconf->peer_name;
166 hlist_add_head(&patch_vport->hash_node, hash_bucket(peer_name));
167 rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(peer_name));
168 update_peers(patch_vport->name, vport);
172 error_free_patchconf:
175 ovs_vport_free(vport);
180 static void free_port_rcu(struct rcu_head *rcu)
182 struct patch_vport *patch_vport = container_of(rcu,
183 struct patch_vport, rcu);
185 kfree((struct patch_config __force *)patch_vport->patchconf);
186 ovs_vport_free(vport_from_priv(patch_vport));
189 static void patch_destroy(struct vport *vport)
191 struct patch_vport *patch_vport = patch_vport_priv(vport);
193 update_peers(patch_vport->name, NULL);
194 hlist_del(&patch_vport->hash_node);
195 call_rcu(&patch_vport->rcu, free_port_rcu);
198 static int patch_set_options(struct vport *vport, struct nlattr *options)
200 struct patch_vport *patch_vport = patch_vport_priv(vport);
201 struct patch_config *patchconf;
204 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
205 sizeof(struct patch_config), GFP_KERNEL);
211 err = patch_set_config(vport, options, patchconf);
215 assign_config_rcu(vport, patchconf);
217 hlist_del(&patch_vport->hash_node);
219 rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(patchconf->peer_name));
220 hlist_add_head(&patch_vport->hash_node, hash_bucket(patchconf->peer_name));
230 static void update_peers(const char *name, struct vport *vport)
232 struct hlist_head *bucket = hash_bucket(name);
233 struct patch_vport *peer_vport;
234 struct hlist_node *node;
236 hlist_for_each_entry(peer_vport, node, bucket, hash_node) {
237 const char *peer_name;
239 peer_name = rtnl_dereference(peer_vport->patchconf)->peer_name;
240 if (!strcmp(peer_name, name))
241 rcu_assign_pointer(peer_vport->peer, vport);
245 static int patch_set_addr(struct vport *vport, const unsigned char *addr)
247 struct patch_vport *patch_vport = patch_vport_priv(vport);
248 struct patch_config *patchconf;
250 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
251 sizeof(struct patch_config), GFP_KERNEL);
255 memcpy(patchconf->eth_addr, addr, ETH_ALEN);
256 assign_config_rcu(vport, patchconf);
262 static const char *patch_get_name(const struct vport *vport)
264 const struct patch_vport *patch_vport = patch_vport_priv(vport);
265 return patch_vport->name;
268 static const unsigned char *patch_get_addr(const struct vport *vport)
270 const struct patch_vport *patch_vport = patch_vport_priv(vport);
271 return rcu_dereference_rtnl(patch_vport->patchconf)->eth_addr;
274 static int patch_get_options(const struct vport *vport, struct sk_buff *skb)
276 struct patch_vport *patch_vport = patch_vport_priv(vport);
277 struct patch_config *patchconf = rcu_dereference_rtnl(patch_vport->patchconf);
279 return nla_put_string(skb, OVS_PATCH_ATTR_PEER, patchconf->peer_name);
282 static int patch_send(struct vport *vport, struct sk_buff *skb)
284 struct patch_vport *patch_vport = patch_vport_priv(vport);
285 struct vport *peer = rcu_dereference(patch_vport->peer);
286 int skb_len = skb->len;
290 ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
295 ovs_vport_receive(peer, skb);
299 const struct vport_ops ovs_patch_vport_ops = {
300 .type = OVS_VPORT_TYPE_PATCH,
303 .create = patch_create,
304 .destroy = patch_destroy,
305 .set_addr = patch_set_addr,
306 .get_name = patch_get_name,
307 .get_addr = patch_get_addr,
308 .get_options = patch_get_options,
309 .set_options = patch_set_options,
310 .get_dev_flags = ovs_vport_gen_get_dev_flags,
311 .is_running = ovs_vport_gen_is_running,
312 .get_operstate = ovs_vport_gen_get_operstate,