X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=73481ddd6da5bd4f01e27d423dfbda8ce4e142ce;hb=ae412e7dd89489911a32c6723d4109c6d1de3a38;hp=16621a9c7560f870a1a775b01a418bff159edadc;hpb=64d64dd7bbecf7baed6975420009a7a613caba2f;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 16621a9c..73481ddd 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -147,6 +147,7 @@ struct port { long long int bond_next_fake_iface_update; /* Time of next update. */ int bond_rebalance_interval; /* Interval between rebalances, in ms. */ long long int bond_next_rebalance; /* Next rebalancing time. */ + struct netdev_monitor *monitor; /* Tracks carrier up/down status. */ /* Port mirroring info. */ mirror_mask_t src_mirrors; /* Mirrors triggered when packet received. */ @@ -1750,7 +1751,7 @@ bridge_reconfigure_remotes(struct bridge *br, if (!n_controllers && ofproto_get_fail_mode(br->ofproto) == OFPROTO_FAIL_STANDALONE) { union ofp_action action; - flow_t flow; + struct flow flow; memset(&action, 0, sizeof action); action.type = htons(OFPAT_OUTPUT); @@ -2054,6 +2055,21 @@ bond_run(struct bridge *br) struct port *port = br->ports[i]; if (port->n_ifaces >= 2) { + char *devname; + + /* Track carrier going up and down on interfaces. */ + while (!netdev_monitor_poll(port->monitor, &devname)) { + struct iface *iface; + bool carrier; + + iface = port_lookup_iface(port, devname); + if (iface && !netdev_get_carrier(iface->netdev, &carrier)) { + bond_link_status_update(iface, carrier); + port_update_bond_compat(port); + } + free(devname); + } + for (j = 0; j < port->n_ifaces; j++) { struct iface *iface = port->ifaces[j]; if (time_msec() >= iface->delay_expires) { @@ -2085,6 +2101,7 @@ bond_wait(struct bridge *br) if (port->n_ifaces < 2) { continue; } + netdev_monitor_poll_wait(port->monitor); for (j = 0; j < port->n_ifaces; j++) { struct iface *iface = port->ifaces[j]; if (iface->delay_expires != LLONG_MAX) { @@ -2098,7 +2115,7 @@ bond_wait(struct bridge *br) } static bool -set_dst(struct dst *p, const flow_t *flow, +set_dst(struct dst *p, const struct flow *flow, const struct port *in_port, const struct port *out_port, tag_type *tags) { @@ -2187,7 +2204,7 @@ port_includes_vlan(const struct port *port, uint16_t vlan) } static size_t -compose_dsts(const struct bridge *br, const flow_t *flow, uint16_t vlan, +compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan, const struct port *in_port, const struct port *out_port, struct dst dsts[], tag_type *tags, uint16_t *nf_output_iface) { @@ -2275,7 +2292,7 @@ print_dsts(const struct dst *dsts, size_t n) } static void -compose_actions(struct bridge *br, const flow_t *flow, uint16_t vlan, +compose_actions(struct bridge *br, const struct flow *flow, uint16_t vlan, const struct port *in_port, const struct port *out_port, tag_type *tags, struct odp_actions *actions, uint16_t *nf_output_iface) @@ -2309,7 +2326,7 @@ compose_actions(struct bridge *br, const flow_t *flow, uint16_t vlan, * 802.1Q header and implicitly tagged ports. A value of 0 indicates that * the packet is untagged and -1 indicates it has an invalid header and * should be dropped. */ -static int flow_get_vlan(struct bridge *br, const flow_t *flow, +static int flow_get_vlan(struct bridge *br, const struct flow *flow, struct port *in_port, bool have_packet) { /* Note that dl_vlan of 0 and of OFP_VLAN_NONE both mean that the packet @@ -2355,7 +2372,7 @@ static int flow_get_vlan(struct bridge *br, const flow_t *flow, * migration. Older Citrix-patched Linux DomU used gratuitous ARP replies to * indicate this; newer upstream kernels use gratuitous ARP requests. */ static bool -is_gratuitous_arp(const flow_t *flow) +is_gratuitous_arp(const struct flow *flow) { return (flow->dl_type == htons(ETH_TYPE_ARP) && eth_addr_is_broadcast(flow->dl_dst) @@ -2365,7 +2382,7 @@ is_gratuitous_arp(const flow_t *flow) } static void -update_learning_table(struct bridge *br, const flow_t *flow, int vlan, +update_learning_table(struct bridge *br, const struct flow *flow, int vlan, struct port *in_port) { enum grat_arp_lock_type lock_type; @@ -2413,7 +2430,7 @@ update_learning_table(struct bridge *br, const flow_t *flow, int vlan, * so in one special case. */ static bool -is_admissible(struct bridge *br, const flow_t *flow, bool have_packet, +is_admissible(struct bridge *br, const struct flow *flow, bool have_packet, tag_type *tags, int *vlanp, struct port **in_portp) { struct iface *in_iface; @@ -2502,7 +2519,7 @@ is_admissible(struct bridge *br, const flow_t *flow, bool have_packet, * returns true. Otherwise, the actions should only be applied to 'packet', or * not at all, if 'packet' was NULL. */ static bool -process_flow(struct bridge *br, const flow_t *flow, +process_flow(struct bridge *br, const struct flow *flow, const struct ofpbuf *packet, struct odp_actions *actions, tag_type *tags, uint16_t *nf_output_iface) { @@ -2552,45 +2569,8 @@ done: return true; } -/* Careful: 'opp' is in host byte order and opp->port_no is an OFP port - * number. */ -static void -bridge_port_changed_ofhook_cb(enum ofp_port_reason reason, - const struct ofp_phy_port *opp, - void *br_) -{ - struct bridge *br = br_; - struct iface *iface; - struct port *port; - - iface = iface_from_dp_ifidx(br, ofp_port_to_odp_port(opp->port_no)); - if (!iface) { - return; - } - port = iface->port; - - if (reason == OFPPR_DELETE) { - VLOG_WARN("bridge %s: interface %s deleted unexpectedly", - br->name, iface->name); - iface_destroy(iface); - if (!port->n_ifaces) { - VLOG_WARN("bridge %s: port %s has no interfaces, dropping", - br->name, port->name); - port_destroy(port); - } - - bridge_flush(br); - } else { - if (port->n_ifaces > 1) { - bool up = !(opp->state & OFPPS_LINK_DOWN); - bond_link_status_update(iface, up); - port_update_bond_compat(port); - } - } -} - static bool -bridge_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet, +bridge_normal_ofhook_cb(const struct flow *flow, const struct ofpbuf *packet, struct odp_actions *actions, tag_type *tags, uint16_t *nf_output_iface, void *br_) { @@ -2602,7 +2582,7 @@ bridge_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet, } static void -bridge_account_flow_ofhook_cb(const flow_t *flow, tag_type tags, +bridge_account_flow_ofhook_cb(const struct flow *flow, tag_type tags, const union odp_action *actions, size_t n_actions, unsigned long long int n_bytes, void *br_) @@ -2662,7 +2642,6 @@ bridge_account_checkpoint_ofhook_cb(void *br_) } static struct ofhooks bridge_ofhooks = { - bridge_port_changed_ofhook_cb, bridge_normal_ofhook_cb, bridge_account_flow_ofhook_cb, bridge_account_checkpoint_ofhook_cb, @@ -2984,7 +2963,7 @@ bond_send_learning_packets(struct port *port) union ofp_action actions[2], *a; uint16_t dp_ifidx; tag_type tags = 0; - flow_t flow; + struct flow flow; int retval; if (e->port == port->port_idx @@ -3551,6 +3530,7 @@ port_destroy(struct port *port) del = br->ports[port->port_idx] = br->ports[--br->n_ports]; del->port_idx = port->port_idx; + netdev_monitor_destroy(port->monitor); free(port->ifaces); bitmap_free(port->trunks); free(port->name); @@ -3582,6 +3562,10 @@ port_lookup_iface(const struct port *port, const char *name) static void port_update_bonding(struct port *port) { + if (port->monitor) { + netdev_monitor_destroy(port->monitor); + port->monitor = NULL; + } if (port->n_ifaces < 2) { /* Not a bonded port. */ if (port->bond_hash) { @@ -3591,9 +3575,9 @@ port_update_bonding(struct port *port) port->bond_fake_iface = false; } } else { - if (!port->bond_hash) { - size_t i; + size_t i; + if (!port->bond_hash) { port->bond_hash = xcalloc(BOND_MASK + 1, sizeof *port->bond_hash); for (i = 0; i <= BOND_MASK; i++) { struct bond_entry *e = &port->bond_hash[i]; @@ -3611,6 +3595,11 @@ port_update_bonding(struct port *port) } port->bond_compat_is_stale = true; port->bond_fake_iface = port->cfg->bond_fake_iface; + + port->monitor = netdev_monitor_create(); + for (i = 0; i < port->n_ifaces; i++) { + netdev_monitor_add(port->monitor, port->ifaces[i]->netdev); + } } }