struct ofpbuf * flow_mod_conjunction(enum ofputil_protocol proto) { struct ofputil_flow_mod fm; struct ofpbuf acts; struct ofpact_conjunction *a_conj; memset(&fm, 0, sizeof(fm)); fm.command = OFPFC_ADD; fm.table_id = 4; fm.new_cookie = htonll(0x123456789abcdef0); fm.cookie_mask = OVS_BE64_MAX; fm.importance = 0x9878; fill_match(&fm.match); ofpbuf_init(&acts, 64); a_conj = ofpact_put_CONJUNCTION(&acts); a_conj->id = 0xabcdef; a_conj->clause = 1; a_conj->n_clauses = 2; fm.ofpacts = acts.data; fm.ofpacts_len = acts.size; return ofputil_encode_flow_mod(&fm, proto); }
/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command' * (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'. * '*cur_format' should initially contain the flow format currently configured * on the connection; this function will add a message to change the flow * format and update '*cur_format', if this is necessary to add the parsed * flow. */ void parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, char *string, uint16_t command) { bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT; enum nx_flow_format min_format, next_format; struct ofpbuf actions; struct ofpbuf *ofm; struct flow_mod fm; ofpbuf_init(&actions, 64); parse_ofp_str(&fm, NULL, is_del ? NULL : &actions, string); fm.command = command; min_format = ofputil_min_flow_format(&fm.cr, true, fm.cookie); next_format = MAX(*cur_format, min_format); if (next_format != *cur_format) { struct ofpbuf *sff = ofputil_make_set_flow_format(next_format); list_push_back(packets, &sff->list_node); *cur_format = next_format; } ofm = ofputil_encode_flow_mod(&fm, *cur_format); list_push_back(packets, &ofm->list_node); ofpbuf_uninit(&actions); }
struct ofpbuf * flow_mod_match_conj(enum ofputil_protocol proto) { struct ofputil_flow_mod fm; struct ofpbuf acts; struct ofpact_ipv4 *a_set_field; struct ofpact_goto_table *a_goto; memset(&fm, 0, sizeof(fm)); fm.command = OFPFC_ADD; fm.table_id = 3; fm.new_cookie = htonll(0x123456789abcdef0); fm.cookie_mask = OVS_BE64_MAX; fm.importance = 0x9878; match_init_catchall(&fm.match); match_set_conj_id(&fm.match, 0xabcdef); ofpbuf_init(&acts, 64); ofpact_put_STRIP_VLAN(&acts); a_set_field = ofpact_put_SET_IPV4_DST(&acts); a_set_field->ipv4 = inet_addr("192.168.2.9"); a_goto = ofpact_put_GOTO_TABLE(&acts); a_goto->table_id = 100; fm.ofpacts = acts.data; fm.ofpacts_len = acts.size; return ofputil_encode_flow_mod(&fm, proto); }
void ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg *bms, size_t n_bms, struct ovs_list *requests, enum ofputil_protocol protocol) { enum ofp_version version = ofputil_protocol_to_ofp_version(protocol); for (size_t i = 0; i < n_bms; i++) { struct ofpbuf *request = NULL; switch ((int)bms[i].type) { case OFPTYPE_FLOW_MOD: request = ofputil_encode_flow_mod(&bms[i].fm, protocol); break; case OFPTYPE_GROUP_MOD: request = ofputil_encode_group_mod(version, &bms[i].gm, NULL, -1); break; case OFPTYPE_PACKET_OUT: request = ofputil_encode_packet_out(&bms[i].po, protocol); break; default: break; } if (request) { ovs_list_push_back(requests, &request->list_node); } } }
struct ofpbuf * flow_mod(enum ofputil_protocol proto) { struct ofputil_flow_mod fm; struct ofpbuf acts; struct ofpact_ipv4 *a_set_field; struct ofpact_goto_table *a_goto; char *error; /* * Taken from neutron OVS-agent, * modified for OF>=1.3. (NXM -> OXM) * NOTE(yamamoto): This needs to be writable. learn_parse() modifies it. */ char learn_args[] = "table=99," "priority=1," "hard_timeout=300," "OXM_OF_VLAN_VID[0..11]," "OXM_OF_ETH_DST[]=OXM_OF_ETH_SRC[]," "load:0->OXM_OF_VLAN_VID[]," "load:OXM_OF_TUNNEL_ID[]->OXM_OF_TUNNEL_ID[]," "output:OXM_OF_IN_PORT[]"; memset(&fm, 0, sizeof(fm)); fm.command = OFPFC_ADD; fm.table_id = 2; fm.new_cookie = htonll(0x123456789abcdef0); fm.cookie_mask = OVS_BE64_MAX; fm.importance = 0x9878; fill_match(&fm.match); ofpbuf_init(&acts, 64); ofpact_put_STRIP_VLAN(&acts); a_set_field = ofpact_put_SET_IPV4_DST(&acts); a_set_field->ipv4 = inet_addr("192.168.2.9"); error = learn_parse(learn_args, &acts); assert(error == NULL); a_goto = ofpact_put_GOTO_TABLE(&acts); a_goto->table_id = 100; fm.ofpacts = acts.data; fm.ofpacts_len = acts.size; return ofputil_encode_flow_mod(&fm, proto); }
static void lswitch_handshake(struct lswitch *sw) { enum ofputil_protocol protocol; enum ofp_version version; send_features_request(sw); send_controller_id(sw); version = rconn_get_version(sw->rconn); protocol = ofputil_protocol_from_ofp_version(version); if (sw->default_flows) { struct ofpbuf *msg = NULL; int error = 0; size_t i; if (!(protocol & sw->usable_protocols)) { enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols); while (!error) { msg = ofputil_encode_set_protocol(protocol, want, &protocol); if (!msg) { break; } error = rconn_send(sw->rconn, msg, NULL); } } if (protocol & sw->usable_protocols) { for (i = 0; !error && i < sw->n_default_flows; i++) { msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol); error = rconn_send(sw->rconn, msg, NULL); } if (error) { VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)", rconn_get_name(sw->rconn), ovs_strerror(error)); } } else { VLOG_INFO_RL(&rl, "%s: failed to set usable protocol", rconn_get_name(sw->rconn)); } } sw->protocol = protocol; }
OfpBuf FlowExecutor::EncodeMod<FlowEdit::Entry>(const FlowEdit::Entry& edit, int ofVersion) { ofputil_protocol proto = ofputil_protocol_from_ofp_version((ofp_version)ofVersion); assert(ofputil_protocol_is_valid(proto)); FlowEdit::type mod = edit.first; ofputil_flow_stats& flow = *(edit.second->entry); ofputil_flow_mod flowMod; memset(&flowMod, 0, sizeof(flowMod)); flowMod.table_id = flow.table_id; flowMod.priority = flow.priority; if (mod != FlowEdit::ADD) { flowMod.cookie = flow.cookie; flowMod.cookie_mask = ~((uint64_t)0); } flowMod.new_cookie = mod == FlowEdit::MOD ? OVS_BE64_MAX : (mod == FlowEdit::ADD ? flow.cookie : 0); memcpy(&flowMod.match, &flow.match, sizeof(flow.match)); if (mod != FlowEdit::DEL) { flowMod.ofpacts_len = flow.ofpacts_len; flowMod.ofpacts = (ofpact*)flow.ofpacts; } flowMod.command = mod == FlowEdit::ADD ? OFPFC_ADD : (mod == FlowEdit::MOD ? OFPFC_MODIFY_STRICT : OFPFC_DELETE_STRICT); /* fill out defaults */ flowMod.modify_cookie = false; flowMod.idle_timeout = OFP_FLOW_PERMANENT; flowMod.hard_timeout = OFP_FLOW_PERMANENT; flowMod.buffer_id = UINT32_MAX; flowMod.out_port = OFPP_NONE; flowMod.out_group = OFPG_ANY; flowMod.flags = (ofputil_flow_mod_flags)0; if (flow.flags) flowMod.flags = flow.flags; return OfpBuf(ofputil_encode_flow_mod(&flowMod, proto)); }
/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command' * (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'. * '*cur_format' should initially contain the flow format currently configured * on the connection; this function will add a message to change the flow * format and update '*cur_format', if this is necessary to add the parsed * flow. */ void parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, bool *flow_mod_table_id, char *string, uint16_t command, bool verbose) { enum nx_flow_format min_format, next_format; struct cls_rule rule_copy; struct ofpbuf *ofm; struct ofputil_flow_mod fm; parse_ofp_str(&fm, command, string, verbose); min_format = ofputil_min_flow_format(&fm.cr); if (command != OFPFC_ADD && fm.cookie_mask != htonll(0)) { min_format = NXFF_NXM; } next_format = MAX(*cur_format, min_format); if (next_format != *cur_format) { struct ofpbuf *sff = ofputil_make_set_flow_format(next_format); list_push_back(packets, &sff->list_node); *cur_format = next_format; } /* Normalize a copy of the rule. This ensures that non-normalized flows * get logged but doesn't affect what gets sent to the switch, so that the * switch can do whatever it likes with the flow. */ rule_copy = fm.cr; ofputil_normalize_rule(&rule_copy, next_format); if (fm.table_id != 0xff && !*flow_mod_table_id) { struct ofpbuf *sff = ofputil_make_flow_mod_table_id(true); list_push_back(packets, &sff->list_node); *flow_mod_table_id = true; } ofm = ofputil_encode_flow_mod(&fm, *cur_format, *flow_mod_table_id); list_push_back(packets, &ofm->list_node); }