X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=926f278f952509abb201ab8cdbce8da31f75f2a1;hb=b2f460c72dc738302adf44b988e9dc4b44c4c621;hp=7299cd17d2e9227c89d2e91d3d09ffe58c061b6a;hpb=330a8abb28a997e8fe2b61cef8f1197d9807afeb;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 7299cd17..926f278f 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -218,28 +218,30 @@ static int create_dp(int dp_idx, const char __user *devnamep) dp = kzalloc(sizeof *dp, GFP_KERNEL); if (dp == NULL) goto err_put_module; - + INIT_LIST_HEAD(&dp->port_list); mutex_init(&dp->mutex); dp->dp_idx = dp_idx; for (i = 0; i < DP_N_QUEUES; i++) skb_queue_head_init(&dp->queues[i]); init_waitqueue_head(&dp->waitqueue); + /* Allocate table. */ + err = -ENOMEM; + rcu_assign_pointer(dp->table, dp_table_create(DP_L1_SIZE)); + if (!dp->table) + goto err_free_dp; + /* Setup our datapath device */ dp_dev = dp_dev_create(dp, devname, ODPP_LOCAL); err = PTR_ERR(dp_dev); if (IS_ERR(dp_dev)) - goto err_free_dp; - - err = -ENOMEM; - rcu_assign_pointer(dp->table, dp_table_create(DP_L1_SIZE)); - if (!dp->table) - goto err_destroy_dp_dev; - INIT_LIST_HEAD(&dp->port_list); + goto err_destroy_table; err = new_nbp(dp, dp_dev, ODPP_LOCAL); - if (err) + if (err) { + dp_dev_destroy(dp_dev); goto err_destroy_table; + } dp->drop_frags = 0; dp->stats_percpu = alloc_percpu(struct dp_stats_percpu); @@ -256,11 +258,9 @@ static int create_dp(int dp_idx, const char __user *devnamep) return 0; err_destroy_local_port: - dp_del_port(dp->ports[ODPP_LOCAL], NULL); + dp_del_port(dp->ports[ODPP_LOCAL]); err_destroy_table: dp_table_destroy(dp->table, 0); -err_destroy_dp_dev: - dp_dev_destroy(dp_dev); err_free_dp: kfree(dp); err_put_module: @@ -272,21 +272,21 @@ err: return err; } -static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs) +static void do_destroy_dp(struct datapath *dp) { struct net_bridge_port *p, *n; int i; list_for_each_entry_safe (p, n, &dp->port_list, node) if (p->port_no != ODPP_LOCAL) - dp_del_port(p, dp_devs); + dp_del_port(p); if (dp_del_dp_hook) dp_del_dp_hook(dp); rcu_assign_pointer(dps[dp->dp_idx], NULL); - dp_del_port(dp->ports[ODPP_LOCAL], dp_devs); + dp_del_port(dp->ports[ODPP_LOCAL]); dp_table_destroy(dp->table, 1); @@ -301,9 +301,7 @@ static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs) static int destroy_dp(int dp_idx) { - struct dp_dev *dp_dev, *next; struct datapath *dp; - LIST_HEAD(dp_devs); int err; rtnl_lock(); @@ -313,14 +311,12 @@ static int destroy_dp(int dp_idx) if (!dp) goto err_unlock; - do_destroy_dp(dp, &dp_devs); + do_destroy_dp(dp); err = 0; err_unlock: mutex_unlock(&dp_mutex); rtnl_unlock(); - list_for_each_entry_safe (dp_dev, next, &dp_devs, list) - free_netdev(dp_dev->dev); return err; } @@ -421,7 +417,7 @@ out: return err; } -int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) +int dp_del_port(struct net_bridge_port *p) { ASSERT_RTNL(); @@ -454,10 +450,6 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) if (is_dp_dev(p->dev)) { dp_dev_destroy(p->dev); - if (dp_devs) { - struct dp_dev *dp_dev = dp_dev_priv(p->dev); - list_add(&dp_dev->list, dp_devs); - } } if (p->port_no != ODPP_LOCAL && dp_del_if_hook) { dp_del_if_hook(p); @@ -471,7 +463,6 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs) static int del_port(int dp_idx, int port_no) { - struct dp_dev *dp_dev, *next; struct net_bridge_port *p; struct datapath *dp; LIST_HEAD(dp_devs); @@ -492,15 +483,13 @@ static int del_port(int dp_idx, int port_no) if (!p) goto out_unlock_dp; - err = dp_del_port(p, &dp_devs); + err = dp_del_port(p); out_unlock_dp: mutex_unlock(&dp->mutex); out_unlock_rtnl: rtnl_unlock(); out: - list_for_each_entry_safe (dp_dev, next, &dp_devs, list) - free_netdev(dp_dev->dev); return err; } @@ -531,7 +520,6 @@ void dp_process_received_packet(struct sk_buff *skb, struct net_bridge_port *p) struct sw_flow *flow; WARN_ON_ONCE(skb_shared(skb)); - WARN_ON_ONCE(skb->destructor); /* BHs are off so we don't have to use get_cpu()/put_cpu() here. */ stats = percpu_ptr(dp->stats_percpu, smp_processor_id()); @@ -580,8 +568,7 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb) #error #endif -#ifdef CONFIG_XEN -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18) +#if defined(CONFIG_XEN) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18) /* This code is copied verbatim from net/dev/core.c in Xen's * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644. We can't call those functions * directly because they aren't exported. */ @@ -597,7 +584,7 @@ static int skb_pull_up_to(struct sk_buff *skb, void *ptr) } } -int skb_checksum_setup(struct sk_buff *skb) +int vswitch_skb_checksum_setup(struct sk_buff *skb) { if (skb->proto_csum_blank) { if (skb->protocol != htons(ETH_P_IP)) @@ -628,8 +615,9 @@ int skb_checksum_setup(struct sk_buff *skb) out: return -EPROTO; } -#endif /* linux == 2.6.18 */ -#endif /* CONFIG_XEN */ +#else +int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; } +#endif /* CONFIG_XEN && linux == 2.6.18 */ int dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no, @@ -655,7 +643,7 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no, * the non-Xen case, but it is difficult to trigger or test this case * there, hence the WARN_ON_ONCE(). */ - err = skb_checksum_setup(skb); + err = vswitch_skb_checksum_setup(skb); if (err) goto err_kfree_skb; #ifndef CHECKSUM_HW @@ -1260,7 +1248,7 @@ list_ports(struct datapath *dp, struct odp_portvec __user *pvp) break; } } - return put_user(idx, &pvp->n_ports); + return put_user(dp->n_ports, &pvp->n_ports); } /* RCU callback for freeing a dp_port_group */ @@ -1344,24 +1332,28 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, /* Handle commands with special locking requirements up front. */ switch (cmd) { case ODP_DP_CREATE: - return create_dp(dp_idx, (char __user *)argp); + err = create_dp(dp_idx, (char __user *)argp); + goto exit; case ODP_DP_DESTROY: - return destroy_dp(dp_idx); + err = destroy_dp(dp_idx); + goto exit; case ODP_PORT_ADD: - return add_port(dp_idx, (struct odp_port __user *)argp); + err = add_port(dp_idx, (struct odp_port __user *)argp); + goto exit; case ODP_PORT_DEL: err = get_user(port_no, (int __user *)argp); - if (err) - return err; - return del_port(dp_idx, port_no); + if (!err) + err = del_port(dp_idx, port_no); + goto exit; } dp = get_dp_locked(dp_idx); + err = -ENODEV; if (!dp) - return -ENODEV; + goto exit; switch (cmd) { case ODP_DP_STATS: @@ -1443,6 +1435,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, break; } mutex_unlock(&dp->mutex); +exit: return err; }