2 * Copyright (c) 2010, 2011 Nicira Networks.
3 * Distributed under the terms of the GNU GPL version 2.
5 * Significant portions of this file may be copied from parts of the Linux
6 * kernel, by Linus Torvalds and others.
9 #include <linux/dcache.h>
10 #include <linux/kernel.h>
11 #include <linux/list.h>
12 #include <linux/rtnetlink.h>
16 #include "vport-generic.h"
21 char peer_name
[IFNAMSIZ
];
22 unsigned char eth_addr
[ETH_ALEN
];
30 /* Protected by RTNL lock. */
31 struct hlist_node hash_node
;
33 struct vport __rcu
*peer
;
34 struct patch_config __rcu
*patchconf
;
37 /* Protected by RTNL lock. */
38 static struct hlist_head
*peer_table
;
39 #define PEER_HASH_BUCKETS 256
41 static void update_peers(const char *name
, struct vport
*);
43 static inline struct patch_vport
*patch_vport_priv(const struct vport
*vport
)
45 return vport_priv(vport
);
49 static void free_config(struct rcu_head
*rcu
)
51 struct patch_config
*c
= container_of(rcu
, struct patch_config
, rcu
);
55 static void assign_config_rcu(struct vport
*vport
,
56 struct patch_config
*new_config
)
58 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
59 struct patch_config
*old_config
;
61 old_config
= rtnl_dereference(patch_vport
->patchconf
);
62 rcu_assign_pointer(patch_vport
->patchconf
, new_config
);
63 call_rcu(&old_config
->rcu
, free_config
);
66 static struct hlist_head
*hash_bucket(const char *name
)
68 unsigned int hash
= full_name_hash(name
, strlen(name
));
69 return &peer_table
[hash
& (PEER_HASH_BUCKETS
- 1)];
72 static int patch_init(void)
74 peer_table
= kzalloc(PEER_HASH_BUCKETS
* sizeof(struct hlist_head
),
82 static void patch_exit(void)
87 static const struct nla_policy patch_policy
[ODP_PATCH_ATTR_MAX
+ 1] = {
88 #ifdef HAVE_NLA_NUL_STRING
89 [ODP_PATCH_ATTR_PEER
] = { .type
= NLA_NUL_STRING
, .len
= IFNAMSIZ
- 1 },
93 static int patch_set_config(struct vport
*vport
, const struct nlattr
*options
,
94 struct patch_config
*patchconf
)
96 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
97 struct nlattr
*a
[ODP_PATCH_ATTR_MAX
+ 1];
98 const char *peer_name
;
104 err
= nla_parse_nested(a
, ODP_PATCH_ATTR_MAX
, options
, patch_policy
);
108 if (!a
[ODP_PATCH_ATTR_PEER
] || VERIFY_NUL_STRING(a
[ODP_PATCH_ATTR_PEER
], IFNAMSIZ
- 1))
111 peer_name
= nla_data(a
[ODP_PATCH_ATTR_PEER
]);
112 if (!strcmp(patch_vport
->name
, peer_name
))
115 strcpy(patchconf
->peer_name
, peer_name
);
120 static struct vport
*patch_create(const struct vport_parms
*parms
)
123 struct patch_vport
*patch_vport
;
124 const char *peer_name
;
125 struct patch_config
*patchconf
;
128 vport
= vport_alloc(sizeof(struct patch_vport
), &patch_vport_ops
, parms
);
130 err
= PTR_ERR(vport
);
134 patch_vport
= patch_vport_priv(vport
);
136 strcpy(patch_vport
->name
, parms
->name
);
138 patchconf
= kmalloc(sizeof(struct patch_config
), GFP_KERNEL
);
141 goto error_free_vport
;
144 err
= patch_set_config(vport
, parms
->options
, patchconf
);
146 goto error_free_patchconf
;
148 vport_gen_rand_ether_addr(patchconf
->eth_addr
);
150 rcu_assign_pointer(patch_vport
->patchconf
, patchconf
);
152 peer_name
= patchconf
->peer_name
;
153 hlist_add_head(&patch_vport
->hash_node
, hash_bucket(peer_name
));
154 rcu_assign_pointer(patch_vport
->peer
, vport_locate(peer_name
));
155 update_peers(patch_vport
->name
, vport
);
159 error_free_patchconf
:
167 static void free_port_rcu(struct rcu_head
*rcu
)
169 struct patch_vport
*patch_vport
= container_of(rcu
,
170 struct patch_vport
, rcu
);
172 kfree((struct patch_config __force
*)patch_vport
->patchconf
);
173 vport_free(vport_from_priv(patch_vport
));
176 static int patch_destroy(struct vport
*vport
)
178 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
180 update_peers(patch_vport
->name
, NULL
);
181 hlist_del(&patch_vport
->hash_node
);
182 call_rcu(&patch_vport
->rcu
, free_port_rcu
);
187 static int patch_set_options(struct vport
*vport
, struct nlattr
*options
)
189 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
190 struct patch_config
*patchconf
;
193 patchconf
= kmemdup(rtnl_dereference(patch_vport
->patchconf
),
194 sizeof(struct patch_config
), GFP_KERNEL
);
200 err
= patch_set_config(vport
, options
, patchconf
);
204 assign_config_rcu(vport
, patchconf
);
206 hlist_del(&patch_vport
->hash_node
);
208 rcu_assign_pointer(patch_vport
->peer
, vport_locate(patchconf
->peer_name
));
209 hlist_add_head(&patch_vport
->hash_node
, hash_bucket(patchconf
->peer_name
));
219 static void update_peers(const char *name
, struct vport
*vport
)
221 struct hlist_head
*bucket
= hash_bucket(name
);
222 struct patch_vport
*peer_vport
;
223 struct hlist_node
*node
;
225 hlist_for_each_entry(peer_vport
, node
, bucket
, hash_node
) {
226 const char *peer_name
;
228 peer_name
= rtnl_dereference(peer_vport
->patchconf
)->peer_name
;
229 if (!strcmp(peer_name
, name
))
230 rcu_assign_pointer(peer_vport
->peer
, vport
);
234 static int patch_set_addr(struct vport
*vport
, const unsigned char *addr
)
236 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
237 struct patch_config
*patchconf
;
239 patchconf
= kmemdup(rtnl_dereference(patch_vport
->patchconf
),
240 sizeof(struct patch_config
), GFP_KERNEL
);
244 memcpy(patchconf
->eth_addr
, addr
, ETH_ALEN
);
245 assign_config_rcu(vport
, patchconf
);
251 static const char *patch_get_name(const struct vport
*vport
)
253 const struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
254 return patch_vport
->name
;
257 static const unsigned char *patch_get_addr(const struct vport
*vport
)
259 const struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
260 return rcu_dereference_rtnl(patch_vport
->patchconf
)->eth_addr
;
263 static int patch_get_options(const struct vport
*vport
, struct sk_buff
*skb
)
265 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
266 struct patch_config
*patchconf
= rcu_dereference_rtnl(patch_vport
->patchconf
);
268 return nla_put_string(skb
, ODP_PATCH_ATTR_PEER
, patchconf
->peer_name
);
271 static int patch_send(struct vport
*vport
, struct sk_buff
*skb
)
273 struct patch_vport
*patch_vport
= patch_vport_priv(vport
);
274 struct vport
*peer
= rcu_dereference(patch_vport
->peer
);
275 int skb_len
= skb
->len
;
279 vport_record_error(vport
, VPORT_E_TX_DROPPED
);
284 vport_receive(peer
, skb
);
288 const struct vport_ops patch_vport_ops
= {
289 .type
= ODP_VPORT_TYPE_PATCH
,
290 .flags
= VPORT_F_GEN_STATS
,
293 .create
= patch_create
,
294 .destroy
= patch_destroy
,
295 .set_addr
= patch_set_addr
,
296 .get_name
= patch_get_name
,
297 .get_addr
= patch_get_addr
,
298 .get_options
= patch_get_options
,
299 .set_options
= patch_set_options
,
300 .get_dev_flags
= vport_gen_get_dev_flags
,
301 .is_running
= vport_gen_is_running
,
302 .get_operstate
= vport_gen_get_operstate
,