static void send_bogus_packet_ins(struct fail_open *fo) { struct eth_addr mac; struct dp_packet b; dp_packet_init(&b, 128); eth_addr_nicira_random(&mac); compose_rarp(&b, mac); struct ofproto_async_msg am = { .oam = OAM_PACKET_IN, .pin = { .up = { .public = { .packet = dp_packet_data(&b), .packet_len = dp_packet_size(&b), .flow_metadata = MATCH_CATCHALL_INITIALIZER, .flow_metadata.flow.in_port.ofp_port = OFPP_LOCAL, .flow_metadata.wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX), .reason = OFPR_NO_MATCH, .cookie = OVS_BE64_MAX, }, }, .max_len = UINT16_MAX, }
/* Parse a queue status request message into 'oqsr'. * Returns 0 if successful, otherwise an OFPERR_* number. */ enum ofperr ofputil_decode_queue_stats_request(const struct ofp_header *request, struct ofputil_queue_stats_request *oqsr) { switch ((enum ofp_version)request->version) { case OFP16_VERSION: case OFP15_VERSION: case OFP14_VERSION: case OFP13_VERSION: case OFP12_VERSION: case OFP11_VERSION: { const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request); oqsr->queue_id = ntohl(qsr11->queue_id); return ofputil_port_from_ofp11(qsr11->port_no, &oqsr->port_no); } case OFP10_VERSION: { const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request); oqsr->queue_id = ntohl(qsr10->queue_id); oqsr->port_no = u16_to_ofp(ntohs(qsr10->port_no)); /* OF 1.0 uses OFPP_ALL for OFPP_ANY */ if (oqsr->port_no == OFPP_ALL) { oqsr->port_no = OFPP_ANY; } return 0; } default: OVS_NOT_REACHED(); } }
/* Convert 'str_' (as described in the documentation for the "monitor" command * in the ovs-ofctl man page) into 'fmr'. */ void parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, const char *str_) { static uint32_t id; char *string = xstrdup(str_); char *save_ptr = NULL; char *name; fmr->id = id++; fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY | NXFMF_OWN | NXFMF_ACTIONS); fmr->out_port = OFPP_NONE; fmr->table_id = 0xff; match_init_catchall(&fmr->match); for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { const struct protocol *p; if (!strcmp(name, "!initial")) { fmr->flags &= ~NXFMF_INITIAL; } else if (!strcmp(name, "!add")) { fmr->flags &= ~NXFMF_ADD; } else if (!strcmp(name, "!delete")) { fmr->flags &= ~NXFMF_DELETE; } else if (!strcmp(name, "!modify")) { fmr->flags &= ~NXFMF_MODIFY; } else if (!strcmp(name, "!actions")) { fmr->flags &= ~NXFMF_ACTIONS; } else if (!strcmp(name, "!own")) { fmr->flags &= ~NXFMF_OWN; } else if (parse_protocol(name, &p)) { match_set_dl_type(&fmr->match, htons(p->dl_type)); if (p->nw_proto) { match_set_nw_proto(&fmr->match, p->nw_proto); } } else { char *value; value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { ovs_fatal(0, "%s: field %s missing value", str_, name); } if (!strcmp(name, "table")) { fmr->table_id = str_to_u8(value, name); } else if (!strcmp(name, "out_port")) { fmr->out_port = u16_to_ofp(atoi(value)); } else if (mf_from_name(name)) { parse_field(mf_from_name(name), value, &fmr->match); } else { ovs_fatal(0, "%s: unknown keyword %s", str_, name); } } } free(string); }
static enum ofperr ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats *oqs, const struct ofp10_queue_stats *qs10) { oqs->port_no = u16_to_ofp(ntohs(qs10->port_no)); oqs->queue_id = ntohl(qs10->queue_id); oqs->tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes)); oqs->tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets)); oqs->tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors)); oqs->duration_sec = oqs->duration_nsec = UINT32_MAX; return 0; }
static void parse_enqueue(char *arg, struct ofpbuf *ofpacts) { char *sp = NULL; char *port = strtok_r(arg, ":q", &sp); char *queue = strtok_r(NULL, "", &sp); struct ofpact_enqueue *enqueue; if (port == NULL || queue == NULL) { ovs_fatal(0, "\"enqueue\" syntax is \"enqueue:PORT:QUEUE\""); } enqueue = ofpact_put_ENQUEUE(ofpacts); enqueue->port = u16_to_ofp(str_to_u32(port)); enqueue->queue = str_to_u32(queue); }
static void parse_output(char *arg, struct ofpbuf *ofpacts) { if (strchr(arg, '[')) { struct ofpact_output_reg *output_reg; output_reg = ofpact_put_OUTPUT_REG(ofpacts); mf_parse_subfield(&output_reg->src, arg); output_reg->max_len = UINT16_MAX; } else { struct ofpact_output *output; output = ofpact_put_OUTPUT(ofpacts); output->port = u16_to_ofp(str_to_u32(arg)); output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0; } }
/* Parses OFPT_QUEUE_GET_CONFIG request 'oh', storing the port specified by the * request into '*port'. Returns 0 if successful, otherwise an OpenFlow error * code. */ enum ofperr ofputil_decode_queue_get_config_request(const struct ofp_header *oh, ofp_port_t *port, uint32_t *queue) { const struct ofp10_queue_get_config_request *qgcr10; const struct ofp11_queue_get_config_request *qgcr11; const struct ofp14_queue_desc_request *qdr14; struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); enum ofpraw raw = ofpraw_pull_assert(&b); switch ((int) raw) { case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST: qgcr10 = b.data; *port = u16_to_ofp(ntohs(qgcr10->port)); *queue = OFPQ_ALL; break; case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST: qgcr11 = b.data; *queue = OFPQ_ALL; enum ofperr error = ofputil_port_from_ofp11(qgcr11->port, port); if (error || *port == OFPP_ANY) { return error; } break; case OFPRAW_OFPST14_QUEUE_DESC_REQUEST: qdr14 = b.data; *queue = ntohl(qdr14->queue); return ofputil_port_from_ofp11(qdr14->port, port); default: OVS_NOT_REACHED(); } return (ofp_to_u16(*port) < ofp_to_u16(OFPP_MAX) ? 0 : OFPERR_OFPQOFC_BAD_PORT); }
/* Composes 'fm' so that executing it will implement 'learn' given that the * packet being processed has 'flow' as its flow. * * Uses 'ofpacts' to store the flow mod's actions. The caller must initialize * 'ofpacts' and retains ownership of it. 'fm->ofpacts' will point into the * 'ofpacts' buffer. * * The caller has to actually execute 'fm'. */ void learn_execute(const struct ofpact_learn *learn, const struct flow *flow, struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts) { const struct ofpact_learn_spec *spec; match_init_catchall(&fm->match); fm->priority = learn->priority; fm->cookie = htonll(0); fm->cookie_mask = htonll(0); fm->new_cookie = learn->cookie; fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX; fm->table_id = learn->table_id; fm->command = OFPFC_MODIFY_STRICT; fm->idle_timeout = learn->idle_timeout; fm->hard_timeout = learn->hard_timeout; fm->importance = 0; fm->buffer_id = UINT32_MAX; fm->out_port = OFPP_NONE; fm->flags = 0; if (learn->flags & NX_LEARN_F_SEND_FLOW_REM) { fm->flags |= OFPUTIL_FF_SEND_FLOW_REM; } fm->ofpacts = NULL; fm->ofpacts_len = 0; fm->delete_reason = OFPRR_DELETE; if (learn->fin_idle_timeout || learn->fin_hard_timeout) { struct ofpact_fin_timeout *oft; oft = ofpact_put_FIN_TIMEOUT(ofpacts); oft->fin_idle_timeout = learn->fin_idle_timeout; oft->fin_hard_timeout = learn->fin_hard_timeout; } for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) { struct ofpact_set_field *sf; union mf_subvalue value; if (spec->src_type == NX_LEARN_SRC_FIELD) { mf_read_subfield(&spec->src, flow, &value); } else { value = spec->src_imm; } switch (spec->dst_type) { case NX_LEARN_DST_MATCH: mf_write_subfield(&spec->dst, &value, &fm->match); break; case NX_LEARN_DST_LOAD: sf = ofpact_put_reg_load(ofpacts); sf->field = spec->dst.field; bitwise_copy(&value, sizeof value, 0, &sf->value, spec->dst.field->n_bytes, spec->dst.ofs, spec->n_bits); bitwise_one(&sf->mask, spec->dst.field->n_bytes, spec->dst.ofs, spec->n_bits); break; case NX_LEARN_DST_OUTPUT: if (spec->n_bits <= 16 || is_all_zeros(value.u8, sizeof value - 2)) { ovs_be16 *last_be16 = &value.be16[ARRAY_SIZE(value.be16) - 1]; ofp_port_t port = u16_to_ofp(ntohs(*last_be16)); if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX) || port == OFPP_IN_PORT || port == OFPP_FLOOD || port == OFPP_LOCAL || port == OFPP_ALL) { ofpact_put_OUTPUT(ofpacts)->port = port; } } break; } } ofpact_pad(ofpacts); fm->ofpacts = ofpbuf_data(ofpacts); fm->ofpacts_len = ofpbuf_size(ofpacts); }
/* Composes 'fm' so that executing it will implement 'learn' given that the * packet being processed has 'flow' as its flow. * * Uses 'ofpacts' to store the flow mod's actions. The caller must initialize * 'ofpacts' and retains ownership of it. 'fm->ofpacts' will point into the * 'ofpacts' buffer. * * The caller has to actually execute 'fm'. */ void learn_execute(const struct ofpact_learn *learn, const struct flow *flow, struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts) { const struct ofpact_learn_spec *spec; match_init_catchall(&fm->match); fm->priority = learn->priority; fm->cookie = htonll(0); fm->cookie_mask = htonll(0); fm->new_cookie = htonll(learn->cookie); fm->table_id = learn->table_id; fm->command = OFPFC_MODIFY_STRICT; fm->idle_timeout = learn->idle_timeout; fm->hard_timeout = learn->hard_timeout; fm->buffer_id = UINT32_MAX; fm->out_port = OFPP_NONE; fm->flags = learn->flags; fm->ofpacts = NULL; fm->ofpacts_len = 0; if (learn->fin_idle_timeout || learn->fin_hard_timeout) { struct ofpact_fin_timeout *oft; oft = ofpact_put_FIN_TIMEOUT(ofpacts); oft->fin_idle_timeout = learn->fin_idle_timeout; oft->fin_hard_timeout = learn->fin_hard_timeout; } for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) { union mf_subvalue value; int chunk, ofs; if (spec->src_type == NX_LEARN_SRC_FIELD) { mf_read_subfield(&spec->src, flow, &value); } else { value = spec->src_imm; } switch (spec->dst_type) { case NX_LEARN_DST_MATCH: mf_write_subfield(&spec->dst, &value, &fm->match); break; case NX_LEARN_DST_LOAD: for (ofs = 0; ofs < spec->n_bits; ofs += chunk) { struct ofpact_reg_load *load; chunk = MIN(spec->n_bits - ofs, 64); load = ofpact_put_REG_LOAD(ofpacts); load->dst.field = spec->dst.field; load->dst.ofs = spec->dst.ofs + ofs; load->dst.n_bits = chunk; bitwise_copy(&value, sizeof value, ofs, &load->subvalue, sizeof load->subvalue, 0, chunk); } break; case NX_LEARN_DST_OUTPUT: if (spec->n_bits <= 16 || is_all_zeros(value.u8, sizeof value - 2)) { ofp_port_t port = u16_to_ofp(ntohs(value.be16[7])); if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX) || port == OFPP_IN_PORT || port == OFPP_FLOOD || port == OFPP_LOCAL || port == OFPP_ALL) { ofpact_put_OUTPUT(ofpacts)->port = port; } } break; } } ofpact_pad(ofpacts); fm->ofpacts = ofpacts->data; fm->ofpacts_len = ofpacts->size; }
void match_set_in_port(struct match *match, ofp_port_t ofp_port) { match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX); match->flow.in_port.ofp_port = ofp_port; }
/* Composes 'fm' so that executing it will implement 'learn' given that the * packet being processed has 'flow' as its flow. * * Uses 'ofpacts' to store the flow mod's actions. The caller must initialize * 'ofpacts' and retains ownership of it. 'fm->ofpacts' will point into the * 'ofpacts' buffer. * * The caller has to actually execute 'fm'. */ void learn_execute(const struct ofpact_learn *learn, const struct flow *flow, struct ofputil_flow_mod *fm, struct ofpbuf *ofpacts) { const struct ofpact_learn_spec *spec; match_init_catchall(&fm->match); fm->priority = learn->priority; fm->cookie = htonll(0); fm->cookie_mask = htonll(0); fm->new_cookie = learn->cookie; fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX; fm->table_id = learn->table_id; fm->command = OFPFC_MODIFY_STRICT; fm->idle_timeout = learn->idle_timeout; fm->hard_timeout = learn->hard_timeout; fm->importance = 0; fm->buffer_id = UINT32_MAX; fm->out_port = OFPP_NONE; fm->ofpacts_tlv_bitmap = 0; fm->flags = 0; if (learn->flags & NX_LEARN_F_SEND_FLOW_REM) { fm->flags |= OFPUTIL_FF_SEND_FLOW_REM; } fm->ofpacts = NULL; fm->ofpacts_len = 0; if (learn->fin_idle_timeout || learn->fin_hard_timeout) { struct ofpact_fin_timeout *oft; oft = ofpact_put_FIN_TIMEOUT(ofpacts); oft->fin_idle_timeout = learn->fin_idle_timeout; oft->fin_hard_timeout = learn->fin_hard_timeout; } OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) { struct ofpact_set_field *sf; union mf_subvalue value; if (spec->src_type == NX_LEARN_SRC_FIELD) { mf_read_subfield(&spec->src, flow, &value); } else { mf_subvalue_from_value(&spec->dst, &value, ofpact_learn_spec_imm(spec)); } switch (spec->dst_type) { case NX_LEARN_DST_MATCH: mf_write_subfield(&spec->dst, &value, &fm->match); match_add_ethernet_prereq(&fm->match, spec->dst.field); mf_vl_mff_set_tlv_bitmap( spec->dst.field, &fm->match.flow.tunnel.metadata.present.map); break; case NX_LEARN_DST_LOAD: sf = ofpact_put_reg_load(ofpacts, spec->dst.field, NULL, NULL); bitwise_copy(&value, sizeof value, 0, sf->value, spec->dst.field->n_bytes, spec->dst.ofs, spec->n_bits); bitwise_one(ofpact_set_field_mask(sf), spec->dst.field->n_bytes, spec->dst.ofs, spec->n_bits); mf_vl_mff_set_tlv_bitmap(spec->dst.field, &fm->ofpacts_tlv_bitmap); break; case NX_LEARN_DST_OUTPUT: if (spec->n_bits <= 16 || is_all_zeros(value.u8, sizeof value - 2)) { ofp_port_t port = u16_to_ofp(ntohll(value.integer)); if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX) || port == OFPP_IN_PORT || port == OFPP_FLOOD || port == OFPP_LOCAL || port == OFPP_ALL) { ofpact_put_OUTPUT(ofpacts)->port = port; } } break; } } fm->ofpacts = ofpacts->data; fm->ofpacts_len = ofpacts->size; }
static int ofputil_pull_queue_get_config_reply10(struct ofpbuf *msg, struct ofputil_queue_config *queue) { const struct ofp_header *oh = msg->header; unsigned int opq_len; /* Length of protocol-specific queue header. */ unsigned int len; /* Total length of queue + properties. */ /* Obtain the port number from the message header. */ if (oh->version == OFP10_VERSION) { const struct ofp10_queue_get_config_reply *oqgcr10 = msg->msg; queue->port = u16_to_ofp(ntohs(oqgcr10->port)); } else { const struct ofp11_queue_get_config_reply *oqgcr11 = msg->msg; enum ofperr error = ofputil_port_from_ofp11(oqgcr11->port, &queue->port); if (error) { return error; } } /* Pull off the queue header and get the queue number and length. */ if (oh->version < OFP12_VERSION) { const struct ofp10_packet_queue *opq10; opq10 = ofpbuf_try_pull(msg, sizeof *opq10); if (!opq10) { return OFPERR_OFPBRC_BAD_LEN; } queue->queue = ntohl(opq10->queue_id); len = ntohs(opq10->len); opq_len = sizeof *opq10; } else { const struct ofp12_packet_queue *opq12; opq12 = ofpbuf_try_pull(msg, sizeof *opq12); if (!opq12) { return OFPERR_OFPBRC_BAD_LEN; } queue->queue = ntohl(opq12->queue_id); len = ntohs(opq12->len); opq_len = sizeof *opq12; } /* Length check. */ if (len < opq_len || len > msg->size + opq_len || len % 8) { return OFPERR_OFPBRC_BAD_LEN; } len -= opq_len; /* Pull properties. The format of these properties differs from used in * OF1.4+ so we can't use the common property functions. */ while (len > 0) { const struct ofp10_queue_prop_header *hdr; unsigned int property; unsigned int prop_len; enum ofperr error = 0; hdr = ofpbuf_at_assert(msg, 0, sizeof *hdr); prop_len = ntohs(hdr->len); if (prop_len < sizeof *hdr || prop_len > len || prop_len % 8) { return OFPERR_OFPBRC_BAD_LEN; } property = ntohs(hdr->property); switch (property) { case OFPQT10_MIN_RATE: error = parse_ofp10_queue_rate(hdr, &queue->min_rate); break; case OFPQT11_MAX_RATE: error = parse_ofp10_queue_rate(hdr, &queue->max_rate); break; default: VLOG_INFO_RL(&rl, "unknown queue property %u", property); break; } if (error) { return error; } ofpbuf_pull(msg, prop_len); len -= prop_len; } return 0; }