bool enabled; /* May be chosen for flows? */
bool up; /* Is the interface up? */
const char *type; /* Usually same as cfg->type. */
- struct cfm *cfm; /* Connectivity Fault Management */
const struct ovsrec_interface *cfg;
/* LACP information. */
/* LACP information. */
struct lacp *lacp; /* LACP object. NULL if LACP is disabled. */
bool lacp_active; /* True if LACP is active */
+ bool lacp_fast; /* True if LACP is in fast mode. */
uint16_t lacp_priority; /* LACP system priority. */
/* SLB specific bonding info. */
static void iface_update_qos(struct iface *, const struct ovsrec_qos *);
static void iface_update_cfm(struct iface *);
static void iface_refresh_cfm_stats(struct iface *iface);
-static void iface_send_packet(struct iface *, struct ofpbuf *packet);
-static void iface_update_carrier(struct iface *, bool carrier);
+static void iface_update_carrier(struct iface *);
+static bool iface_get_carrier(const struct iface *);
static void shash_from_ovs_idl_map(char **keys, char **values, size_t n,
struct shash *);
static void shash_to_ovs_idl_map(struct shash *,
char ***keys, char ***values, size_t *n);
-
/* Hooks into ofproto processing. */
static struct ofhooks bridge_ofhooks;
\f
/* Update 'iface'. */
if (iface) {
iface->netdev = netdev;
- iface->enabled = netdev_get_carrier(iface->netdev);
+ iface->enabled = iface_get_carrier(iface);
iface->up = iface->enabled;
}
} else if (iface && iface->netdev) {
ovsrec_interface_set_link_state(iface->cfg,
- netdev_get_carrier(iface->netdev)
- ? "up" : "down");
+ iface_get_carrier(iface) ? "up" : "down");
error = netdev_get_mtu(iface->netdev, &mtu);
if (!error && mtu != INT_MAX) {
static void
iface_refresh_cfm_stats(struct iface *iface)
{
- size_t i;
- struct cfm *cfm;
const struct ovsrec_monitor *mon;
+ const struct cfm *cfm;
+ size_t i;
mon = iface->cfg->monitor;
- cfm = iface->cfm;
+ cfm = ofproto_iface_get_cfm(iface->port->bridge->ofproto, iface->dp_ifidx);
if (!cfm || !mon) {
return;
iface = iface_from_dp_ifidx(br, flow->in_port);
- if (cfm_should_process_flow(flow)) {
-
- if (iface && packet && iface->cfm) {
- COVERAGE_INC(bridge_process_cfm);
- cfm_process_heartbeat(iface->cfm, packet);
- }
- return false;
- } else if (flow->dl_type == htons(ETH_TYPE_LACP)) {
+ if (flow->dl_type == htons(ETH_TYPE_LACP)) {
if (iface && iface->port->lacp && packet) {
const struct lacp_pdu *pdu = parse_lacp_packet(packet);
ofpbuf_init(&packet, 128);
error = n_packets = n_errors = 0;
LIST_FOR_EACH (e, lru_node, &br->ml->lrus) {
- union ofp_action actions[2], *a;
- uint16_t dp_ifidx;
tag_type tags = 0;
+ uint16_t dp_ifidx;
struct flow flow;
int retval;
continue;
}
- /* Compose actions. */
- memset(actions, 0, sizeof actions);
- a = actions;
- if (e->vlan) {
- a->vlan_vid.type = htons(OFPAT_SET_VLAN_VID);
- a->vlan_vid.len = htons(sizeof *a);
- a->vlan_vid.vlan_vid = htons(e->vlan);
- a++;
- }
- a->output.type = htons(OFPAT_OUTPUT);
- a->output.len = htons(sizeof *a);
- a->output.port = htons(odp_port_to_ofp_port(dp_ifidx));
- a++;
-
/* Send packet. */
n_packets++;
- retval = ofproto_send_packet(br->ofproto, &flow, actions, a - actions,
- &packet);
+ retval = ofproto_send_packet(br->ofproto, dp_ifidx, e->vlan, &packet);
if (retval) {
error = retval;
n_errors++;
ofpbuf_init(&packet, ETH_HEADER_LEN + LACP_PDU_LEN);
compose_lacp_packet(&packet, ea, pdu);
- iface_send_packet(iface, &packet);
+ ofproto_send_packet(iface->port->bridge->ofproto,
+ iface->dp_ifidx, 0, &packet);
ofpbuf_uninit(&packet);
} else {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
static void
port_run(struct port *port)
{
- size_t i;
-
if (port->monitor) {
char *devname;
iface = port_lookup_iface(port, devname);
if (iface) {
- iface_update_carrier(iface, netdev_get_carrier(iface->netdev));
+ iface_update_carrier(iface);
}
free(devname);
}
} else if (time_msec() >= port->miimon_next_update) {
+ size_t i;
for (i = 0; i < port->n_ifaces; i++) {
struct iface *iface = port->ifaces[i];
- iface_update_carrier(iface, netdev_get_miimon(iface->netdev));
+ iface_update_carrier(iface);
}
port->miimon_next_update = time_msec() + port->miimon_interval;
}
if (port->lacp) {
+ size_t i;
+
for (i = 0; i < port->n_ifaces; i++) {
struct iface *iface = port->ifaces[i];
lacp_slave_enable(port->lacp, iface, iface->enabled);
}
bond_run(port);
-
- for (i = 0; i < port->n_ifaces; i++) {
- struct iface *iface = port->ifaces[i];
-
- if (iface->cfm) {
- struct ofpbuf *packet = cfm_run(iface->cfm);
- if (packet) {
- iface_send_packet(iface, packet);
- ofpbuf_uninit(packet);
- free(packet);
- }
- }
- }
}
static void
port_wait(struct port *port)
{
- size_t i;
-
if (port->monitor) {
netdev_monitor_poll_wait(port->monitor);
} else {
}
bond_wait(port);
-
- for (i = 0; i < port->n_ifaces; i++) {
- struct iface *iface = port->ifaces[i];
- if (iface->cfm) {
- cfm_wait(iface->cfm);
- }
- }
}
static struct port *
}
shash_destroy(&new_ifaces);
+ port->lacp_fast = !strcmp(get_port_other_config(cfg, "lacp-time", "slow"),
+ "fast");
+
lacp_priority =
atoi(get_port_other_config(cfg, "lacp-system-priority", "0"));
lacp_configure(port->lacp, port->name,
port->bridge->ea, port->lacp_priority,
- port->lacp_active);
+ port->lacp_active, port->lacp_fast);
for (i = 0; i < port->n_ifaces; i++) {
struct iface *iface = port->ifaces[i];
\f
/* Interface functions. */
-static void
-iface_send_packet(struct iface *iface, struct ofpbuf *packet)
-{
- struct flow flow;
- union ofp_action action;
-
- memset(&action, 0, sizeof action);
- action.output.type = htons(OFPAT_OUTPUT);
- action.output.len = htons(sizeof action);
- action.output.port = htons(odp_port_to_ofp_port(iface->dp_ifidx));
-
- flow_extract(packet, 0, ODPP_NONE, &flow);
-
- if (ofproto_send_packet(iface->port->bridge->ofproto, &flow, &action, 1,
- packet)) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- VLOG_WARN_RL(&rl, "interface %s: Failed to send packet.", iface->name);
- }
-}
-
static struct iface *
iface_create(struct port *port, const struct ovsrec_interface *if_cfg)
{
bond_send_learning_packets(port);
}
- cfm_destroy(iface->cfm);
-
free(iface->name);
free(iface);
}
static void
-iface_update_carrier(struct iface *iface, bool carrier)
+iface_update_carrier(struct iface *iface)
{
+ bool carrier = iface_get_carrier(iface);
if (carrier == iface->up) {
return;
}
iface_update_cfm(struct iface *iface)
{
size_t i;
- struct cfm *cfm;
+ struct cfm cfm;
uint16_t *remote_mps;
struct ovsrec_monitor *mon;
uint8_t ea[ETH_ADDR_LEN], maid[CCM_MAID_LEN];
mon = iface->cfg->monitor;
if (!mon) {
- cfm_destroy(iface->cfm);
- iface->cfm = NULL;
+ ofproto_iface_clear_cfm(iface->port->bridge->ofproto, iface->dp_ifidx);
return;
}
return;
}
- if (!iface->cfm) {
- iface->cfm = cfm_create();
- }
-
- cfm = iface->cfm;
- cfm->mpid = mon->mpid;
- cfm->interval = mon->interval ? *mon->interval : 1000;
+ cfm.mpid = mon->mpid;
+ cfm.interval = mon->interval ? *mon->interval : 1000;
- memcpy(cfm->eth_src, ea, sizeof cfm->eth_src);
- memcpy(cfm->maid, maid, sizeof cfm->maid);
+ memcpy(cfm.eth_src, ea, sizeof cfm.eth_src);
+ memcpy(cfm.maid, maid, sizeof cfm.maid);
remote_mps = xzalloc(mon->n_remote_mps * sizeof *remote_mps);
for(i = 0; i < mon->n_remote_mps; i++) {
remote_mps[i] = mon->remote_mps[i]->mpid;
}
- cfm_update_remote_mps(cfm, remote_mps, mon->n_remote_mps);
+
+ ofproto_iface_set_cfm(iface->port->bridge->ofproto, iface->dp_ifidx,
+ &cfm, remote_mps, mon->n_remote_mps);
free(remote_mps);
+}
- if (!cfm_configure(iface->cfm)) {
- cfm_destroy(iface->cfm);
- iface->cfm = NULL;
- }
+/* Read carrier or miimon status directly from 'iface''s netdev, according to
+ * how 'iface''s port is configured.
+ *
+ * Returns true if 'iface' is up, false otherwise. */
+static bool
+iface_get_carrier(const struct iface *iface)
+{
+ return (iface->port->monitor
+ ? netdev_get_carrier(iface->netdev)
+ : netdev_get_miimon(iface->netdev));
}
\f
/* Port mirroring. */