X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=564d303979a64b6546d2537d15d100e0758a2780;hb=1400bbb7eb5b3dc4fc5997d319c14bfb12665151;hp=0ec226d9dcf061c73428a4bbe2df51d7e69a4b8d;hpb=55ecbead3945d0220f14da489e8cf35fa6d4d4bc;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 0ec226d9..564d3039 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -88,12 +88,10 @@ DEFINE_MUTEX(dp_mutex); EXPORT_SYMBOL(dp_mutex); static int dp_maint_func(void *data); -static int update_port_status(struct net_bridge_port *p); -static int send_port_status(struct net_bridge_port *p, uint8_t status); +static void init_port_status(struct net_bridge_port *p); static int dp_genl_openflow_done(struct netlink_callback *); static struct net_bridge_port *new_nbp(struct datapath *, struct net_device *, int port_no); -static int del_switch_port(struct net_bridge_port *); /* nla_shrink - reduce amount of space reserved by nla_reserve * @skb: socket buffer from which to recover room @@ -309,7 +307,7 @@ static int new_dp(int dp_idx) return 0; err_destroy_local_port: - del_switch_port(dp->local_port); + dp_del_switch_port(dp->local_port); err_destroy_chain: chain_destroy(dp->chain); err_destroy_dp_dev: @@ -378,16 +376,16 @@ int add_switch_port(struct datapath *dp, struct net_device *dev) if (IS_ERR(p)) return PTR_ERR(p); - update_port_status(p); + init_port_status(p); /* Notify the ctlpath that this port has been added */ - send_port_status(p, OFPPR_ADD); + dp_send_port_status(p, OFPPR_ADD); return 0; } /* Delete 'p' from switch. */ -static int del_switch_port(struct net_bridge_port *p) +int dp_del_switch_port(struct net_bridge_port *p) { /* First drop references to device. */ cancel_work_sync(&p->port_task); @@ -403,7 +401,7 @@ static int del_switch_port(struct net_bridge_port *p) synchronize_rcu(); /* Notify the ctlpath that this port no longer exists */ - send_port_status(p, OFPPR_DELETE); + dp_send_port_status(p, OFPPR_DELETE); dev_put(p->dev); kfree(p); @@ -419,7 +417,7 @@ static void del_dp(struct datapath *dp) /* Drop references to DP. */ list_for_each_entry_safe (p, n, &dp->port_list, node) - del_switch_port(p); + dp_del_switch_port(p); rcu_assign_pointer(dps[dp->dp_idx], NULL); /* Kill off local_port dev references from buffered packets that have @@ -443,15 +441,6 @@ static int dp_maint_func(void *data) struct datapath *dp = (struct datapath *) data; while (!kthread_should_stop()) { - struct net_bridge_port *p; - - /* Check if port status has changed */ - rcu_read_lock(); - list_for_each_entry_rcu (p, &dp->port_list, node) - if (update_port_status(p)) - send_port_status(p, OFPPR_MOD); - rcu_read_unlock(); - /* Timeout old entries */ chain_timeout(dp->chain); msleep_interruptible(MAINT_SLEEP_MSECS); @@ -886,20 +875,13 @@ dp_update_port_flags(struct datapath *dp, const struct ofp_port_mod *opm) return 0; } -/* Update the port status field of the bridge port. A non-zero return - * value indicates some field has changed. - * - * NB: Callers of this function may hold the RCU read lock, so any - * additional checks must not sleep. - */ -static int -update_port_status(struct net_bridge_port *p) +/* Initialize the port status field of the bridge port. */ +static void +init_port_status(struct net_bridge_port *p) { unsigned long int flags; - uint32_t orig_status; spin_lock_irqsave(&p->lock, flags); - orig_status = p->status; if (p->dev->flags & IFF_UP) p->status &= ~OFPPFL_PORT_DOWN; @@ -912,11 +894,10 @@ update_port_status(struct net_bridge_port *p) p->status |= OFPPFL_LINK_DOWN; spin_unlock_irqrestore(&p->lock, flags); - return (orig_status != p->status); } -static int -send_port_status(struct net_bridge_port *p, uint8_t status) +int +dp_send_port_status(struct net_bridge_port *p, uint8_t status) { struct sk_buff *skb; struct ofp_port_status *ops; @@ -1162,7 +1143,7 @@ static int dp_genl_add_del_port(struct sk_buff *skb, struct genl_info *info) err = -ENOENT; goto out_put; } - err = del_switch_port(port->br_port); + err = dp_del_switch_port(port->br_port); } out_put: @@ -1740,10 +1721,14 @@ static int __init dp_init(void) if (err) goto error; - err = dp_init_netlink(); + err = register_netdevice_notifier(&dp_device_notifier); if (err) goto error_flow_exit; + err = dp_init_netlink(); + if (err) + goto error_unreg_notifier; + /* Hook into callback used by the bridge to intercept packets. * Parasites we are. */ if (br_handle_frame_hook) @@ -1752,6 +1737,8 @@ static int __init dp_init(void) return 0; +error_unreg_notifier: + unregister_netdevice_notifier(&dp_device_notifier); error_flow_exit: flow_exit(); error: @@ -1763,6 +1750,7 @@ static void dp_cleanup(void) { fwd_exit(); dp_uninit_netlink(); + unregister_netdevice_notifier(&dp_device_notifier); flow_exit(); br_handle_frame_hook = NULL; }