X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=e9a4e189464bd9062ae3c83bf4c64e26209e266d;hb=fe4a02e4fa6be030a0478f6b01b0d4b6ab9b808f;hp=4d95e04db747a6c3fad616384b44773cf802b96b;hpb=850b6b3b9f8c38b42e315c2c07d232a33b82da3e;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 4d95e04d..e9a4e189 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2011 Nicira Networks. + * Copyright (c) 2007-2012 Nicira Networks. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -54,15 +54,20 @@ #include "checksum.h" #include "datapath.h" #include "flow.h" +#include "genl_exec.h" #include "vlan.h" #include "tunnel.h" #include "vport-internal_dev.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \ - LINUX_VERSION_CODE > KERNEL_VERSION(3,2,0) + LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) #error Kernels before 2.6.18 or after 3.2 are not supported by this version of Open vSwitch. #endif +#define REHASH_FLOW_INTERVAL (10 * 60 * HZ) +static void rehash_flow_table(struct work_struct *work); +static DECLARE_DELAYED_WORK(rehash_flow_wq, rehash_flow_table); + int (*ovs_dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd); EXPORT_SYMBOL(ovs_dp_ioctl_hook); @@ -395,8 +400,8 @@ static int queue_gso_packets(int dp_ifindex, struct sk_buff *skb, break; if (skb == segs && skb_shinfo(skb)->gso_type & SKB_GSO_UDP) { - /* The initial flow key extracted by flow_extract() in - * this case is for a first fragment, so we need to + /* The initial flow key extracted by ovs_flow_extract() + * in this case is for a first fragment, so we need to * properly mark later fragments. */ later_key = *upcall_info->key; @@ -1545,9 +1550,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) int i = 0; list_for_each_entry(dp, &dps, list_node) { - if (i < skip) - continue; - if (ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid, + if (i >= skip && + ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, OVS_DP_CMD_NEW) < 0) break; @@ -1797,7 +1801,6 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) genl_notify(reply, genl_info_net(info), info->snd_pid, ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL); - exit_unlock: rtnl_unlock(); exit: @@ -2040,6 +2043,29 @@ error: return err; } +static int __rehash_flow_table(void *dummy) +{ + struct datapath *dp; + + list_for_each_entry(dp, &dps, list_node) { + struct flow_table *old_table = genl_dereference(dp->table); + struct flow_table *new_table; + + new_table = ovs_flow_tbl_rehash(old_table); + if (!IS_ERR(new_table)) { + rcu_assign_pointer(dp->table, new_table); + ovs_flow_tbl_deferred_destroy(old_table); + } + } + return 0; +} + +static void rehash_flow_table(struct work_struct *work) +{ + genl_exec(__rehash_flow_table, NULL); + schedule_delayed_work(&rehash_flow_wq, REHASH_FLOW_INTERVAL); +} + static int __init dp_init(void) { struct sk_buff *dummy_skb; @@ -2050,10 +2076,18 @@ static int __init dp_init(void) pr_info("Open vSwitch switching datapath %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR); - err = ovs_tnl_init(); + err = genl_exec_init(); if (err) goto error; + err = ovs_workqueues_init(); + if (err) + goto error_genl_exec; + + err = ovs_tnl_init(); + if (err) + goto error_wq; + err = ovs_flow_init(); if (err) goto error_tnl_exit; @@ -2070,6 +2104,8 @@ static int __init dp_init(void) if (err < 0) goto error_unreg_notifier; + schedule_delayed_work(&rehash_flow_wq, REHASH_FLOW_INTERVAL); + return 0; error_unreg_notifier: @@ -2080,18 +2116,25 @@ error_flow_exit: ovs_flow_exit(); error_tnl_exit: ovs_tnl_exit(); +error_wq: + ovs_workqueues_exit(); +error_genl_exec: + genl_exec_exit(); error: return err; } static void dp_cleanup(void) { + cancel_delayed_work_sync(&rehash_flow_wq); rcu_barrier(); dp_unregister_genl(ARRAY_SIZE(dp_genl_families)); unregister_netdevice_notifier(&ovs_dp_device_notifier); ovs_vport_exit(); ovs_flow_exit(); ovs_tnl_exit(); + ovs_workqueues_exit(); + genl_exec_exit(); } module_init(dp_init);