#include "netlink.h"
#include "nx-match.h"
#include "odp-util.h"
+#include "odp-execute.h"
#include "ofp-util.h"
#include "ofpbuf.h"
#include "ofp-actions.h"
/* Special OpenFlow rules. */
struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */
struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */
+ struct rule_dpif *drop_frags_rule; /* Used in OFPC_FRAG_DROP mode. */
/* Bridging. */
struct netflow *netflow;
ofpbuf_clear(&ofpacts);
error = add_internal_flow(ofproto, id++, &ofpacts,
&ofproto->no_packet_in_rule);
+ if (error) {
+ return error;
+ }
+
+ error = add_internal_flow(ofproto, id++, &ofpacts,
+ &ofproto->drop_frags_rule);
return error;
}
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct dpif_dp_stats s;
- uint64_t n_miss, n_no_pkt_in, n_bytes;
+ uint64_t n_miss, n_no_pkt_in, n_bytes, n_dropped_frags;
uint64_t n_lookup;
strcpy(ots->name, "classifier");
dpif_get_dp_stats(ofproto->backer->dpif, &s);
rule_get_stats(&ofproto->miss_rule->up, &n_miss, &n_bytes);
rule_get_stats(&ofproto->no_packet_in_rule->up, &n_no_pkt_in, &n_bytes);
+ rule_get_stats(&ofproto->drop_frags_rule->up, &n_dropped_frags, &n_bytes);
- n_lookup = s.n_hit + s.n_missed;
+ n_lookup = s.n_hit + s.n_missed - n_dropped_frags;
ots->lookup_count = htonll(n_lookup);
ots->matched_count = htonll(n_lookup - n_miss - n_no_pkt_in);
}
{
struct cls_rule *cls_rule;
struct classifier *cls;
+ bool frag;
if (table_id >= N_TABLES) {
return NULL;
}
cls = &ofproto->up.tables[table_id].cls;
- if (flow->nw_frag & FLOW_NW_FRAG_ANY
- && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) {
- /* For OFPC_NORMAL frag_handling, we must pretend that transport ports
- * are unavailable. */
+ frag = (flow->nw_frag & FLOW_NW_FRAG_ANY) != 0;
+ if (frag && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) {
+ /* We must pretend that transport ports are unavailable. */
struct flow ofpc_normal_flow = *flow;
ofpc_normal_flow.tp_src = htons(0);
ofpc_normal_flow.tp_dst = htons(0);
cls_rule = classifier_lookup(cls, &ofpc_normal_flow);
+ } else if (frag && ofproto->up.frag_handling == OFPC_FRAG_DROP) {
+ cls_rule = &ofproto->drop_frags_rule->up.cr;
} else {
cls_rule = classifier_lookup(cls, flow);
}
{
struct ofputil_packet_in pin;
struct ofpbuf *packet;
+ struct flow key;
ovs_assert(!ctx->xout->slow || ctx->xout->slow == SLOW_CONTROLLER);
ctx->xout->slow = SLOW_CONTROLLER;
packet = ofpbuf_clone(ctx->xin->packet);
- if (packet->l2 && packet->l3) {
- struct eth_header *eh;
- uint16_t mpls_depth;
-
- eth_pop_vlan(packet);
- eh = packet->l2;
-
- memcpy(eh->eth_src, ctx->xin->flow.dl_src, sizeof eh->eth_src);
- memcpy(eh->eth_dst, ctx->xin->flow.dl_dst, sizeof eh->eth_dst);
-
- if (ctx->xin->flow.vlan_tci & htons(VLAN_CFI)) {
- eth_push_vlan(packet, ctx->xin->flow.vlan_tci);
- }
-
- mpls_depth = eth_mpls_depth(packet);
+ key.skb_priority = 0;
+ key.skb_mark = 0;
+ memset(&key.tunnel, 0, sizeof key.tunnel);
- if (mpls_depth < ctx->xin->flow.mpls_depth) {
- push_mpls(packet, ctx->xin->flow.dl_type, ctx->xin->flow.mpls_lse);
- } else if (mpls_depth > ctx->xin->flow.mpls_depth) {
- pop_mpls(packet, ctx->xin->flow.dl_type);
- } else if (mpls_depth) {
- set_mpls_lse(packet, ctx->xin->flow.mpls_lse);
- }
-
- if (packet->l4) {
- if (ctx->xin->flow.dl_type == htons(ETH_TYPE_IP)) {
- packet_set_ipv4(packet, ctx->xin->flow.nw_src,
- ctx->xin->flow.nw_dst, ctx->xin->flow.nw_tos,
- ctx->xin->flow.nw_ttl);
- }
+ commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
+ &ctx->xout->odp_actions);
- if (packet->l7) {
- if (ctx->xin->flow.nw_proto == IPPROTO_TCP) {
- packet_set_tcp_port(packet, ctx->xin->flow.tp_src,
- ctx->xin->flow.tp_dst);
- } else if (ctx->xin->flow.nw_proto == IPPROTO_UDP) {
- packet_set_udp_port(packet, ctx->xin->flow.tp_src,
- ctx->xin->flow.tp_dst);
- }
- }
- }
- }
+ odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data,
+ ctx->xout->odp_actions.size, NULL, NULL);
pin.packet = packet->data;
pin.packet_len = packet->size;
} else if (rule == ofproto->no_packet_in_rule) {
ds_put_cstr(ds, "\nNo match, packets dropped because "
"OFPPC_NO_PACKET_IN is set on in_port.\n");
+ } else if (rule == ofproto->drop_frags_rule) {
+ ds_put_cstr(ds, "\nPackets dropped because they are IP fragments "
+ "and the fragment handling mode is \"drop\".\n");
}
if (rule) {