X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=9cb3f91095000f8a41636ac5392a8754459597cd;hb=fa8b054f50e6f669a1cc4c41ada0f1fdad03e9dd;hp=618e8a56bc848051d07085a71a1d970648b4c9da;hpb=09246b99d1601e2ba7ff85bb26f9b0235632a76d;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 618e8a56b..9cb3f9109 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -88,7 +88,7 @@ struct rule { uint16_t idle_timeout; /* In seconds from time of last use. */ uint16_t hard_timeout; /* In seconds from time of creation. */ bool send_flow_removed; /* Send a flow removed message? */ - long long int used; /* Last-used time (0 if never used). */ + long long int used; /* Time last used; time created if not used. */ long long int created; /* Creation time. */ uint64_t packet_count; /* Number of packets received. */ uint64_t byte_count; /* Number of bytes received. */ @@ -1298,15 +1298,21 @@ ofproto_send_packet(struct ofproto *p, const struct flow *flow, return 0; } +/* Adds a flow to the OpenFlow flow table in 'p' that matches 'cls_rule' and + * performs the 'n_actions' actions in 'actions'. The new flow will not + * timeout. + * + * If cls_rule->priority is in the range of priorities supported by OpenFlow + * (0...65535, inclusive) then the flow will be visible to OpenFlow + * controllers; otherwise, it will be hidden. + * + * The caller retains ownership of 'cls_rule' and 'actions'. */ void ofproto_add_flow(struct ofproto *p, const struct cls_rule *cls_rule, - const union ofp_action *actions, size_t n_actions, - int idle_timeout) + const union ofp_action *actions, size_t n_actions) { struct rule *rule; - rule = rule_create(p, NULL, actions, n_actions, - idle_timeout >= 0 ? idle_timeout : 5 /* XXX */, - 0, 0, false); + rule = rule_create(p, NULL, actions, n_actions, 0, 0, 0, false); rule->cr = *cls_rule; rule_insert(p, rule, NULL, 0); } @@ -2669,6 +2675,36 @@ xlate_set_queue_action(struct action_xlate_ctx *ctx, = priority; } +static void +xlate_set_dl_tci(struct action_xlate_ctx *ctx) +{ + ovs_be16 dl_vlan = ctx->flow.dl_vlan; + uint8_t dl_vlan_pcp = ctx->flow.dl_vlan_pcp; + + if (dl_vlan == htons(OFP_VLAN_NONE)) { + odp_actions_add(ctx->out, ODPAT_STRIP_VLAN); + } else { + union odp_action *oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI); + oa->dl_tci.tci = htons(ntohs(dl_vlan & htons(VLAN_VID_MASK)) + | (dl_vlan_pcp << VLAN_PCP_SHIFT) + | VLAN_CFI); + } +} + +static void +xlate_reg_move_action(struct action_xlate_ctx *ctx, + const struct nx_action_reg_move *narm) +{ + ovs_be16 old_vlan = ctx->flow.dl_vlan; + uint8_t old_pcp = ctx->flow.dl_vlan_pcp; + + nxm_execute_reg_move(narm, &ctx->flow); + + if (ctx->flow.dl_vlan != old_vlan || ctx->flow.dl_vlan_pcp != old_pcp) { + xlate_set_dl_tci(ctx); + } +} + static void xlate_nicira_action(struct action_xlate_ctx *ctx, const struct nx_action_header *nah) @@ -2707,6 +2743,15 @@ xlate_nicira_action(struct action_xlate_ctx *ctx, odp_actions_add(ctx->out, ODPAT_POP_PRIORITY); break; + case NXAST_REG_MOVE: + xlate_reg_move_action(ctx, (const struct nx_action_reg_move *) nah); + break; + + case NXAST_REG_LOAD: + nxm_execute_reg_load((const struct nx_action_reg_load *) nah, + &ctx->flow); + break; + /* If you add a new action here that modifies flow data, don't forget to * update the flow key in ctx->flow at the same time. */ @@ -2742,23 +2787,19 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, break; case OFPAT_SET_VLAN_VID: - oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI); - oa->dl_tci.tci = ia->vlan_vid.vlan_vid; - oa->dl_tci.tci |= htons(ctx->flow.dl_vlan_pcp << VLAN_PCP_SHIFT); ctx->flow.dl_vlan = ia->vlan_vid.vlan_vid; + xlate_set_dl_tci(ctx); break; case OFPAT_SET_VLAN_PCP: - oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI); - oa->dl_tci.tci = htons(ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT); - oa->dl_tci.tci |= ctx->flow.dl_vlan; ctx->flow.dl_vlan_pcp = ia->vlan_pcp.vlan_pcp; + xlate_set_dl_tci(ctx); break; case OFPAT_STRIP_VLAN: - odp_actions_add(ctx->out, ODPAT_STRIP_VLAN); ctx->flow.dl_vlan = htons(OFP_VLAN_NONE); ctx->flow.dl_vlan_pcp = 0; + xlate_set_dl_tci(ctx); break; case OFPAT_SET_DL_SRC: @@ -2884,24 +2925,37 @@ handle_packet_out(struct ofconn *ofconn, struct ofp_header *oh) struct ofproto *p = ofconn->ofproto; struct ofp_packet_out *opo; struct ofpbuf payload, *buffer; - struct odp_actions actions; + union ofp_action *ofp_actions; + struct odp_actions odp_actions; + struct ofpbuf request; struct flow flow; - int n_actions; + size_t n_ofp_actions; uint16_t in_port; int error; + COVERAGE_INC(ofproto_packet_out); + error = reject_slave_controller(ofconn, "OFPT_PACKET_OUT"); if (error) { return error; } - error = check_ofp_packet_out(oh, &payload, &n_actions, p->max_ports); + /* Get ofp_packet_out. */ + request.data = oh; + request.size = ntohs(oh->length); + opo = ofpbuf_try_pull(&request, offsetof(struct ofp_packet_out, actions)); + if (!opo) { + return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); + } + + /* Get actions. */ + error = ofputil_pull_actions(&request, ntohs(opo->actions_len), + &ofp_actions, &n_ofp_actions); if (error) { return error; } - opo = (struct ofp_packet_out *) oh; - COVERAGE_INC(ofproto_packet_out); + /* Get payload. */ if (opo->buffer_id != htonl(UINT32_MAX)) { error = pktbuf_retrieve(ofconn->pktbuf, ntohl(opo->buffer_id), &buffer, &in_port); @@ -2910,18 +2964,29 @@ handle_packet_out(struct ofconn *ofconn, struct ofp_header *oh) } payload = *buffer; } else { + payload = request; buffer = NULL; } - flow_extract(&payload, 0, ofp_port_to_odp_port(ntohs(opo->in_port)), &flow); - error = xlate_actions((const union ofp_action *) opo->actions, n_actions, - &flow, p, &payload, &actions, NULL, NULL, NULL); + /* Extract flow, check actions. */ + flow_extract(&payload, 0, ofp_port_to_odp_port(ntohs(opo->in_port)), + &flow); + error = validate_actions(ofp_actions, n_ofp_actions, &flow, p->max_ports); + if (error) { + goto exit; + } + + /* Send. */ + error = xlate_actions(ofp_actions, n_ofp_actions, &flow, p, &payload, + &odp_actions, NULL, NULL, NULL); if (!error) { - dpif_execute(p->dpif, actions.actions, actions.n_actions, &payload); + dpif_execute(p->dpif, odp_actions.actions, odp_actions.n_actions, + &payload); } - ofpbuf_delete(buffer); - return error; +exit: + ofpbuf_delete(buffer); + return 0; } static void @@ -3640,7 +3705,7 @@ handle_vendor_stats_request(struct ofconn *ofconn, return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR); } - if (ntohs(nsm->header.length) < sizeof(struct nicira_stats_msg)) { + if (ntohs(osr->header.length) < sizeof(struct nicira_stats_msg)) { VLOG_WARN_RL(&rl, "truncated Nicira stats request"); return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } @@ -3998,7 +4063,8 @@ flow_mod_core(struct ofconn *ofconn, struct flow_mod *fm) return error; } - error = validate_actions(fm->actions, fm->n_actions, p->max_ports); + error = validate_actions(fm->actions, fm->n_actions, + &fm->cr.flow, p->max_ports); if (error) { return error; } @@ -4763,8 +4829,7 @@ revalidate_rule(struct ofproto *p, struct rule *rule) rule->super = super; rule->hard_timeout = super->hard_timeout; rule->idle_timeout = super->idle_timeout; - rule->created = super->created; - rule->used = 0; + rule->created = rule->used = super->created; } }