X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=f6eee59a97cdd9a4499056fe048a38fb7529fb19;hb=a61680c6d15fa1f1ae3072a83c0e3d7ed08f6048;hp=4de5a4e63f68c9e737bf77fec560721d5150a971;hpb=21f7563cef5f3e5ab52c15ade58594c2dfdb7195;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4de5a4e63..f6eee59a9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -205,13 +205,13 @@ struct action_xlate_ctx { * reason to look at them. */ int recurse; /* Recursion level, via xlate_table_action. */ - uint32_t priority; /* Current flow priority. 0 if none. */ struct flow base_flow; /* Flow at the last commit. */ - uint32_t base_priority; /* Priority at the last commit. */ + uint32_t original_priority; /* Priority when packet arrived. */ uint8_t table_id; /* OpenFlow table ID where flow was found. */ uint32_t sflow_n_outputs; /* Number of output ports. */ uint16_t sflow_odp_port; /* Output port for composing sFlow action. */ uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */ + bool exit; /* No further actions should be processed. */ }; static void action_xlate_ctx_init(struct action_xlate_ctx *, @@ -949,13 +949,8 @@ send_bpdu_cb(struct ofpbuf *pkt, int port_num, void *ofproto_) VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d " "with unknown MAC", ofproto->up.name, port_num); } else { - int error = netdev_send(ofport->up.netdev, pkt); - if (error) { - VLOG_WARN_RL(&rl, "%s: sending BPDU on port %s failed (%s)", - ofproto->up.name, - netdev_get_name(ofport->up.netdev), - strerror(error)); - } + send_packet(ofproto_dpif_cast(ofport->up.ofproto), + ofport->odp_port, pkt); } } ofpbuf_delete(pkt); @@ -1070,6 +1065,7 @@ set_stp_port(struct ofport *ofport_, if (sp) { ofport->stp_port = NULL; stp_port_disable(sp); + update_stp_port_state(ofport); } return 0; } else if (sp && stp_port_no(sp) != s->port_num @@ -1165,8 +1161,8 @@ stp_process_packet(const struct ofport_dpif *ofport, } /* Trim off padding on payload. */ - if (payload.size > htons(eth->eth_type) + ETH_HEADER_LEN) { - payload.size = htons(eth->eth_type) + ETH_HEADER_LEN; + if (payload.size > ntohs(eth->eth_type) + ETH_HEADER_LEN) { + payload.size = ntohs(eth->eth_type) + ETH_HEADER_LEN; } if (ofpbuf_try_pull(&payload, ETH_HEADER_LEN + LLC_HEADER_LEN)) { @@ -1549,12 +1545,8 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size) pdu_size); memcpy(packet_pdu, pdu, pdu_size); - error = netdev_send(port->up.netdev, &packet); - if (error) { - VLOG_WARN_RL(&rl, "port %s: sending LACP PDU on iface %s failed " - "(%s)", port->bundle->name, - netdev_get_name(port->up.netdev), strerror(error)); - } + send_packet(ofproto_dpif_cast(port->up.ofproto), port->odp_port, + &packet); ofpbuf_uninit(&packet); } else { VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface " @@ -1573,7 +1565,16 @@ bundle_send_learning_packets(struct ofbundle *bundle) error = n_packets = n_errors = 0; LIST_FOR_EACH (e, lru_node, &ofproto->ml->lrus) { if (e->port.p != bundle) { - int ret = bond_send_learning_packet(bundle->bond, e->mac, e->vlan); + struct ofpbuf *learning_packet; + struct ofport_dpif *port; + int ret; + + learning_packet = bond_compose_learning_packet(bundle->bond, e->mac, + e->vlan, + (void **)&port); + ret = send_packet(ofproto_dpif_cast(port->up.ofproto), + port->odp_port, learning_packet); + ofpbuf_delete(learning_packet); if (ret) { error = ret; n_errors++; @@ -2256,7 +2257,8 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls, /* Obtain in_port and tun_id, at least, then set 'flow''s header * pointers. */ odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow); - flow_extract(upcall->packet, flow.tun_id, flow.in_port, &flow); + flow_extract(upcall->packet, flow.priority, flow.tun_id, + flow.in_port, &flow); /* Handle 802.1ag, LACP, and STP specially. */ if (process_special(ofproto, &flow, upcall->packet)) { @@ -3246,7 +3248,7 @@ rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow, } cls = &ofproto->up.tables[table_id]; - if (flow->tos_frag & FLOW_FRAG_ANY + if (flow->frag & FLOW_FRAG_ANY && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) { /* For OFPC_NORMAL frag_handling, we must pretend that transport ports * are unavailable. */ @@ -3448,7 +3450,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, struct flow flow; int error; - flow_extract((struct ofpbuf *) packet, 0, 0, &flow); + flow_extract((struct ofpbuf *) packet, 0, 0, 0, &flow); ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, &flow); @@ -3659,7 +3661,6 @@ static void commit_set_nw_action(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions) { - int frag = base->tos_frag & FLOW_FRAG_MASK; struct ovs_key_ipv4 ipv4_key; if (base->dl_type != htons(ETH_TYPE_IP) || @@ -3669,18 +3670,19 @@ commit_set_nw_action(const struct flow *flow, struct flow *base, if (base->nw_src == flow->nw_src && base->nw_dst == flow->nw_dst && - base->tos_frag == flow->tos_frag) { + base->tos == flow->tos && + base->nw_ttl == flow->nw_ttl && + base->frag == flow->frag) { return; } - - memset(&ipv4_key, 0, sizeof(ipv4_key)); ipv4_key.ipv4_src = base->nw_src = flow->nw_src; ipv4_key.ipv4_dst = base->nw_dst = flow->nw_dst; ipv4_key.ipv4_proto = base->nw_proto; - ipv4_key.ipv4_tos = flow->tos_frag & IP_DSCP_MASK; - ipv4_key.ipv4_frag = (frag == 0 ? OVS_FRAG_TYPE_NONE - : frag == FLOW_FRAG_ANY ? OVS_FRAG_TYPE_FIRST + ipv4_key.ipv4_tos = flow->tos; + ipv4_key.ipv4_ttl = flow->nw_ttl; + ipv4_key.ipv4_frag = (base->frag == 0 ? OVS_FRAG_TYPE_NONE + : base->frag == FLOW_FRAG_ANY ? OVS_FRAG_TYPE_FIRST : OVS_FRAG_TYPE_LATER); commit_action__(odp_actions, OVS_ACTION_ATTR_SET, @@ -3721,19 +3723,17 @@ commit_set_port_action(const struct flow *flow, struct flow *base, } static void -commit_priority_action(struct action_xlate_ctx *ctx) +commit_set_priority_action(const struct flow *flow, struct flow *base, + struct ofpbuf *odp_actions) { - if (ctx->base_priority == ctx->priority) { + if (base->priority == flow->priority) { return; } + base->priority = flow->priority; - if (ctx->priority) { - nl_msg_put_u32(ctx->odp_actions, - OVS_ACTION_ATTR_SET_PRIORITY, ctx->priority); - } else { - nl_msg_put_flag(ctx->odp_actions, OVS_ACTION_ATTR_POP_PRIORITY); - } - ctx->base_priority = ctx->priority; + commit_action__(odp_actions, OVS_ACTION_ATTR_SET, + OVS_KEY_ATTR_PRIORITY, &base->priority, + sizeof(base->priority)); } static void @@ -3748,7 +3748,7 @@ commit_odp_actions(struct action_xlate_ctx *ctx) commit_vlan_action(ctx, flow->vlan_tci); commit_set_nw_action(flow, base, odp_actions); commit_set_port_action(flow, base, odp_actions); - commit_priority_action(ctx); + commit_set_priority_action(flow, base, odp_actions); } static void @@ -3957,7 +3957,7 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx, const struct ofp_action_enqueue *oae) { uint16_t ofp_port, odp_port; - uint32_t ctx_priority, priority; + uint32_t flow_priority, priority; int error; error = dpif_queue_to_priority(ctx->ofproto->dpif, ntohl(oae->queue_id), @@ -3978,10 +3978,10 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx, odp_port = ofp_port_to_odp_port(ofp_port); /* Add datapath actions. */ - ctx_priority = ctx->priority; - ctx->priority = priority; + flow_priority = ctx->flow.priority; + ctx->flow.priority = priority; add_output_action(ctx, odp_port); - ctx->priority = ctx_priority; + ctx->flow.priority = flow_priority; /* Update NetFlow output port. */ if (ctx->nf_output_iface == NF_OUT_DROP) { @@ -4006,7 +4006,7 @@ xlate_set_queue_action(struct action_xlate_ctx *ctx, return; } - ctx->priority = priority; + ctx->flow.priority = priority; } struct xlate_reg_state { @@ -4046,7 +4046,7 @@ slave_enabled_cb(uint16_t ofp_port, void *ofproto_) case OFPP_NORMAL: case OFPP_FLOOD: case OFPP_ALL: - case OFPP_LOCAL: + case OFPP_NONE: return true; case OFPP_CONTROLLER: /* Not supported by the bundle action. */ return false; @@ -4123,6 +4123,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, enum ofputil_action_code code; ovs_be64 tun_id; + if (ctx->exit) { + break; + } + code = ofputil_decode_action_unsafe(ia); switch (code) { case OFPUTIL_OFPAT_OUTPUT: @@ -4163,8 +4167,8 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, break; case OFPUTIL_OFPAT_SET_NW_TOS: - ctx->flow.tos_frag &= ~IP_DSCP_MASK; - ctx->flow.tos_frag |= ia->nw_tos.nw_tos & IP_DSCP_MASK; + ctx->flow.tos &= ~IP_DSCP_MASK; + ctx->flow.tos |= ia->nw_tos.nw_tos & IP_DSCP_MASK; break; case OFPUTIL_OFPAT_SET_TP_SRC: @@ -4200,7 +4204,7 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, break; case OFPUTIL_NXAST_POP_QUEUE: - ctx->priority = 0; + ctx->flow.priority = ctx->original_priority; break; case OFPUTIL_NXAST_REG_MOVE: @@ -4258,6 +4262,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, xlate_learn_action(ctx, (const struct nx_action_learn *) ia); } break; + + case OFPUTIL_NXAST_EXIT: + ctx->exit = true; + break; } } @@ -4289,13 +4297,24 @@ xlate_actions(struct action_xlate_ctx *ctx, ctx->odp_actions = ofpbuf_new(512); ofpbuf_reserve(ctx->odp_actions, NL_A_U32_SIZE); + ctx->tags = 0; + ctx->may_set_up_flow = true; + ctx->has_learn = false; + ctx->has_normal = false; + ctx->nf_output_iface = NF_OUT_DROP; + ctx->recurse = 0; + ctx->original_priority = ctx->flow.priority; + ctx->base_flow = ctx->flow; + ctx->base_flow.tun_id = 0; + ctx->table_id = 0; + ctx->exit = false; - if (ctx->flow.tos_frag & FLOW_FRAG_ANY) { + if (ctx->flow.frag & FLOW_FRAG_ANY) { switch (ctx->ofproto->up.frag_handling) { case OFPC_FRAG_NORMAL: /* We must pretend that transport ports are unavailable. */ - ctx->flow.tp_src = htons(0); - ctx->flow.tp_dst = htons(0); + ctx->flow.tp_src = ctx->base_flow.tp_src = htons(0); + ctx->flow.tp_dst = ctx->base_flow.tp_dst = htons(0); break; case OFPC_FRAG_DROP: @@ -4310,18 +4329,6 @@ xlate_actions(struct action_xlate_ctx *ctx, } } - ctx->tags = 0; - ctx->may_set_up_flow = true; - ctx->has_learn = false; - ctx->has_normal = false; - ctx->nf_output_iface = NF_OUT_DROP; - ctx->recurse = 0; - ctx->priority = 0; - ctx->base_priority = 0; - ctx->base_flow = ctx->flow; - ctx->base_flow.tun_id = 0; - ctx->table_id = 0; - if (process_special(ctx->ofproto, &ctx->flow, ctx->packet)) { ctx->may_set_up_flow = false; return ctx->odp_actions; @@ -5071,6 +5078,10 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet, struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); int error; + if (flow->in_port >= ofproto->max_ports && flow->in_port < OFPP_MAX) { + return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT); + } + error = validate_actions(ofp_actions, n_ofp_actions, flow, ofproto->max_ports); if (!error) { @@ -5109,6 +5120,22 @@ ofproto_dpif_lookup(const char *name) : NULL); } +static void +ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, + const char *args, void *aux OVS_UNUSED) +{ + const struct ofproto_dpif *ofproto; + + ofproto = ofproto_dpif_lookup(args); + if (!ofproto) { + unixctl_command_reply(conn, 501, "no such bridge"); + return; + } + mac_learning_flush(ofproto->ml); + + unixctl_command_reply(conn, 200, "table successfully flushed"); +} + static void ofproto_unixctl_fdb_show(struct unixctl_conn *conn, const char *args, void *aux OVS_UNUSED) @@ -5206,7 +5233,7 @@ static void ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, void *aux OVS_UNUSED) { - char *dpname, *arg1, *arg2, *arg3; + char *dpname, *arg1, *arg2, *arg3, *arg4; char *args = xstrdup(args_); char *save_ptr = NULL; struct ofproto_dpif *ofproto; @@ -5224,7 +5251,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, dpname = strtok_r(args, " ", &save_ptr); arg1 = strtok_r(NULL, " ", &save_ptr); arg2 = strtok_r(NULL, " ", &save_ptr); - arg3 = strtok_r(NULL, "", &save_ptr); /* Get entire rest of line. */ + arg3 = strtok_r(NULL, " ", &save_ptr); + arg4 = strtok_r(NULL, "", &save_ptr); /* Get entire rest of line. */ if (dpname && arg1 && (!arg2 || !strcmp(arg2, "-generate")) && !arg3) { /* ofproto/trace dpname flow [-generate] */ int error; @@ -5249,18 +5277,20 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, packet = ofpbuf_new(0); flow_compose(packet, &flow); } - } else if (dpname && arg1 && arg2 && arg3) { - /* ofproto/trace dpname tun_id in_port packet */ + } else if (dpname && arg1 && arg2 && arg3 && arg4) { + /* ofproto/trace dpname priority tun_id in_port packet */ uint16_t in_port; ovs_be64 tun_id; + uint32_t priority; - tun_id = htonll(strtoull(arg1, NULL, 0)); - in_port = ofp_port_to_odp_port(atoi(arg2)); + priority = atoi(arg1); + tun_id = htonll(strtoull(arg2, NULL, 0)); + in_port = ofp_port_to_odp_port(atoi(arg3)); packet = ofpbuf_new(strlen(args) / 2); - arg3 = ofpbuf_put_hex(packet, arg3, NULL); - arg3 += strspn(arg3, " "); - if (*arg3 != '\0') { + arg4 = ofpbuf_put_hex(packet, arg4, NULL); + arg4 += strspn(arg4, " "); + if (*arg4 != '\0') { unixctl_command_reply(conn, 501, "Trailing garbage in command"); goto exit; } @@ -5275,7 +5305,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, ds_put_cstr(&result, s); free(s); - flow_extract(packet, tun_id, in_port, &flow); + flow_extract(packet, priority, tun_id, in_port, &flow); } else { unixctl_command_reply(conn, 501, "Bad command syntax"); goto exit; @@ -5358,6 +5388,8 @@ ofproto_dpif_unixctl_init(void) unixctl_command_register("ofproto/trace", "bridge {tun_id in_port packet | odp_flow [-generate]}", ofproto_unixctl_trace, NULL); + unixctl_command_register("fdb/flush", "bridge", ofproto_unixctl_fdb_flush, + NULL); unixctl_command_register("fdb/show", "bridge", ofproto_unixctl_fdb_show, NULL); unixctl_command_register("ofproto/clog", "", ofproto_dpif_clog, NULL);