2 * Copyright (c) 2007-2012 Nicira, Inc.
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>
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(struct net *, 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(struct net *net, const char *name)
79 unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
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;
138 struct net *net = ovs_dp_get_net(parms->dp);
141 vport = ovs_vport_alloc(sizeof(struct patch_vport),
142 &ovs_patch_vport_ops, parms);
144 err = PTR_ERR(vport);
148 patch_vport = patch_vport_priv(vport);
150 strcpy(patch_vport->name, parms->name);
152 patchconf = kmalloc(sizeof(struct patch_config), GFP_KERNEL);
155 goto error_free_vport;
158 err = patch_set_config(vport, parms->options, patchconf);
160 goto error_free_patchconf;
162 random_ether_addr(patchconf->eth_addr);
164 rcu_assign_pointer(patch_vport->patchconf, patchconf);
166 peer_name = patchconf->peer_name;
167 hlist_add_head(&patch_vport->hash_node, hash_bucket(net, peer_name));
168 rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(net, peer_name));
169 update_peers(net, patch_vport->name, vport);
173 error_free_patchconf:
176 ovs_vport_free(vport);
181 static void free_port_rcu(struct rcu_head *rcu)
183 struct patch_vport *patch_vport = container_of(rcu,
184 struct patch_vport, rcu);
186 kfree((struct patch_config __force *)patch_vport->patchconf);
187 ovs_vport_free(vport_from_priv(patch_vport));
190 static void patch_destroy(struct vport *vport)
192 struct patch_vport *patch_vport = patch_vport_priv(vport);
194 update_peers(ovs_dp_get_net(vport->dp), patch_vport->name, NULL);
195 hlist_del(&patch_vport->hash_node);
196 call_rcu(&patch_vport->rcu, free_port_rcu);
199 static int patch_set_options(struct vport *vport, struct nlattr *options)
201 struct patch_vport *patch_vport = patch_vport_priv(vport);
202 struct patch_config *patchconf;
205 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
206 sizeof(struct patch_config), GFP_KERNEL);
212 err = patch_set_config(vport, options, patchconf);
216 assign_config_rcu(vport, patchconf);
218 hlist_del(&patch_vport->hash_node);
220 rcu_assign_pointer(patch_vport->peer,
221 ovs_vport_locate(ovs_dp_get_net(vport->dp), patchconf->peer_name));
223 hlist_add_head(&patch_vport->hash_node,
224 hash_bucket(ovs_dp_get_net(vport->dp), patchconf->peer_name));
233 static void update_peers(struct net *net, const char *name, struct vport *vport)
235 struct hlist_head *bucket = hash_bucket(net, name);
236 struct patch_vport *peer_vport;
237 struct hlist_node *node;
239 hlist_for_each_entry(peer_vport, node, bucket, hash_node) {
240 struct vport *curr_vport = vport_from_priv(peer_vport);
241 const char *peer_name;
243 peer_name = rtnl_dereference(peer_vport->patchconf)->peer_name;
244 if (!strcmp(peer_name, name) && net_eq(ovs_dp_get_net(curr_vport->dp), net))
245 rcu_assign_pointer(peer_vport->peer, vport);
249 static int patch_set_addr(struct vport *vport, const unsigned char *addr)
251 struct patch_vport *patch_vport = patch_vport_priv(vport);
252 struct patch_config *patchconf;
254 patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
255 sizeof(struct patch_config), GFP_KERNEL);
259 memcpy(patchconf->eth_addr, addr, ETH_ALEN);
260 assign_config_rcu(vport, patchconf);
266 static const char *patch_get_name(const struct vport *vport)
268 const struct patch_vport *patch_vport = patch_vport_priv(vport);
269 return patch_vport->name;
272 static const unsigned char *patch_get_addr(const struct vport *vport)
274 const struct patch_vport *patch_vport = patch_vport_priv(vport);
275 return rcu_dereference_rtnl(patch_vport->patchconf)->eth_addr;
278 static int patch_get_options(const struct vport *vport, struct sk_buff *skb)
280 struct patch_vport *patch_vport = patch_vport_priv(vport);
281 struct patch_config *patchconf = rcu_dereference_rtnl(patch_vport->patchconf);
283 return nla_put_string(skb, OVS_PATCH_ATTR_PEER, patchconf->peer_name);
286 static int patch_send(struct vport *vport, struct sk_buff *skb)
288 struct patch_vport *patch_vport = patch_vport_priv(vport);
289 struct vport *peer = rcu_dereference(patch_vport->peer);
290 int skb_len = skb->len;
294 ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
299 ovs_vport_receive(peer, skb);
303 const struct vport_ops ovs_patch_vport_ops = {
304 .type = OVS_VPORT_TYPE_PATCH,
307 .create = patch_create,
308 .destroy = patch_destroy,
309 .set_addr = patch_set_addr,
310 .get_name = patch_get_name,
311 .get_addr = patch_get_addr,
312 .get_options = patch_get_options,
313 .set_options = patch_set_options,