- commit_odp_actions(&ctx->flow, &ctx->base_flow, ctx->odp_actions);
- cookie.type = USER_ACTION_COOKIE_CONTROLLER;
- cookie.data = len;
- cookie.n_output = 0;
- cookie.vlan_tci = 0;
- put_userspace_action(ctx->ofproto, ctx->odp_actions, &ctx->flow, &cookie);
+ ctx->may_set_up_flow = false;
+ if (!ctx->packet) {
+ return;
+ }
+
+ packet = ofpbuf_clone(ctx->packet);
+
+ if (packet->l2 && packet->l3) {
+ struct eth_header *eh;
+
+ eth_pop_vlan(packet);
+ eh = packet->l2;
+ assert(eh->eth_type == ctx->flow.dl_type);
+ memcpy(eh->eth_src, ctx->flow.dl_src, sizeof eh->eth_src);
+ memcpy(eh->eth_dst, ctx->flow.dl_dst, sizeof eh->eth_dst);
+
+ if (ctx->flow.vlan_tci & htons(VLAN_CFI)) {
+ eth_push_vlan(packet, ctx->flow.vlan_tci);
+ }
+
+ if (packet->l4) {
+ if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
+ packet_set_ipv4(packet, ctx->flow.nw_src, ctx->flow.nw_dst,
+ ctx->flow.nw_tos, ctx->flow.nw_ttl);
+ }
+
+ if (packet->l7) {
+ if (ctx->flow.nw_proto == IPPROTO_TCP) {
+ packet_set_tcp_port(packet, ctx->flow.tp_src,
+ ctx->flow.tp_dst);
+ } else if (ctx->flow.nw_proto == IPPROTO_UDP) {
+ packet_set_udp_port(packet, ctx->flow.tp_src,
+ ctx->flow.tp_dst);
+ }
+ }
+ }
+ }
+
+ pin.packet = packet->data;
+ pin.packet_len = packet->size;
+ pin.reason = OFPR_ACTION;
+ pin.table_id = ctx->table_id;
+ pin.cookie = ctx->cookie;
+
+ pin.buffer_id = 0;
+ pin.send_len = len;
+ pin.total_len = packet->size;
+ flow_get_metadata(&ctx->flow, &pin.fmd);
+
+ connmgr_send_packet_in(ctx->ofproto->up.connmgr, &pin, &ctx->flow);
+ ofpbuf_delete(packet);