From eca2aeb329f1ebf08cbda14f08197456d903111b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 4 Aug 2008 15:34:26 -0700 Subject: [PATCH] Implement OFPC_FRAG_DROP fragment handling policy. --- datapath/flow.c | 12 ++++++++---- datapath/flow.h | 2 +- datapath/forward.c | 8 +++++++- include/flow.h | 2 +- include/openflow.h | 11 +++++++++-- lib/flow.c | 9 +++++++-- switch/datapath.c | 8 +++++++- 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/datapath/flow.c b/datapath/flow.c index c49a4cb1a..094d32b58 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -211,12 +211,14 @@ static int udphdr_ok(struct sk_buff *skb) } /* Parses the Ethernet frame in 'skb', which was received on 'in_port', - * and initializes 'key' to match. */ -void flow_extract(struct sk_buff *skb, uint16_t in_port, - struct sw_flow_key *key) + * and initializes 'key' to match. Returns 1 if 'skb' contains an IP + * fragment, 0 otherwise. */ +int flow_extract(struct sk_buff *skb, uint16_t in_port, + struct sw_flow_key *key) { struct ethhdr *mac; int nh_ofs, th_ofs; + int retval = 0; key->in_port = htons(in_port); key->wildcards = 0; @@ -292,10 +294,11 @@ void flow_extract(struct sk_buff *skb, uint16_t in_port, } } } else { + retval = 1; goto no_th; } - return; + return 0; } key->nw_src = 0; @@ -307,6 +310,7 @@ no_proto: no_th: key->tp_src = 0; key->tp_dst = 0; + return retval; } /* Initializes the flow module. diff --git a/datapath/flow.h b/datapath/flow.h index e964c71e2..28c2b8b0b 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -83,7 +83,7 @@ int flow_del_matches(const struct sw_flow_key *, const struct sw_flow_key *, struct sw_flow *flow_alloc(int n_actions, gfp_t flags); void flow_free(struct sw_flow *); void flow_deferred_free(struct sw_flow *); -void flow_extract(struct sk_buff *, uint16_t in_port, struct sw_flow_key *); +int flow_extract(struct sk_buff *, uint16_t in_port, struct sw_flow_key *); void flow_extract_match(struct sw_flow_key* to, const struct ofp_match* from); void flow_fill_match(struct ofp_match* to, const struct sw_flow_key* from); diff --git a/datapath/forward.c b/datapath/forward.c index 8e2bc112e..4dee840b4 100644 --- a/datapath/forward.c +++ b/datapath/forward.c @@ -36,7 +36,13 @@ int run_flow_through_tables(struct sw_chain *chain, struct sk_buff *skb, struct sw_flow_key key; struct sw_flow *flow; - flow_extract(skb, in_port, &key); + if (flow_extract(skb, in_port, &key) + && (chain->dp->flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP) { + /* Drop fragment. */ + kfree_skb(skb); + return 0; + } + flow = chain_lookup(chain, &key); if (likely(flow != NULL)) { flow_used(flow, skb); diff --git a/include/flow.h b/include/flow.h index d1043d262..57754c126 100644 --- a/include/flow.h +++ b/include/flow.h @@ -57,7 +57,7 @@ struct flow { }; BUILD_ASSERT_DECL(sizeof (struct flow) == 32); -void flow_extract(struct buffer *, uint16_t in_port, struct flow *); +int flow_extract(struct buffer *, uint16_t in_port, struct flow *); void flow_print(FILE *, const struct flow *); int flow_compare(const struct flow *, const struct flow *); unsigned long int flow_hash(const struct flow *, uint32_t basis); diff --git a/include/openflow.h b/include/openflow.h index 238c571bb..9db427b49 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -132,7 +132,13 @@ OFP_ASSERT(sizeof(struct ofp_header) == 8); enum ofp_config_flags { /* Tells datapath to notify the controller of expired flow entries. */ - OFPC_SEND_FLOW_EXP = 1 << 0 + OFPC_SEND_FLOW_EXP = 1 << 0, + + /* Handling of IP fragments. */ + OFPC_FRAG_NORMAL = 0 << 1, /* No special handling for fragments. */ + OFPC_FRAG_DROP = 1 << 1, /* Drop fragments. */ + OFPC_FRAG_REASM = 2 << 1, /* Reassemble (only if OFPC_IP_REASM set). */ + OFPC_FRAG_MASK = 3 << 1 }; /* Switch configuration. */ @@ -150,8 +156,9 @@ enum ofp_capabilities { OFPC_TABLE_STATS = 1 << 1, /* Table statistics. */ OFPC_PORT_STATS = 1 << 2, /* Port statistics. */ OFPC_STP = 1 << 3, /* 802.11d spanning tree. */ - OFPC_MULTI_PHY_TX = 1 << 4 /* Supports transmitting through multiple + OFPC_MULTI_PHY_TX = 1 << 4, /* Supports transmitting through multiple physical interfaces */ + OFPC_IP_REASM = 1 << 5 /* Can reassemble IP fragments. */ }; /* Flags to indicate behavior of the physical port */ diff --git a/lib/flow.c b/lib/flow.c index 7a943d713..f534f5797 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -88,11 +88,13 @@ pull_vlan(struct buffer *packet) return buffer_try_pull(packet, VLAN_HEADER_LEN); } -void +/* Returns 1 if 'packet' is an IP fragment, 0 otherwise. */ +int flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow) { struct buffer b = *packet; struct eth_header *eth; + int retval = 0; if (b.size < ETH_TOTAL_MIN) { /* This message is not too useful since there are various ways that we @@ -121,7 +123,7 @@ flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow) /* This is an 802.2 frame */ struct llc_snap_header *h = buffer_at(&b, 0, sizeof *h); if (h == NULL) { - return; + return 0; } if (h->llc.llc_dsap == LLC_DSAP_SNAP && h->llc.llc_ssap == LLC_SSAP_SNAP @@ -179,10 +181,13 @@ flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow) flow->nw_proto = 0; } } + } else { + retval = 1; } } } } + return retval; } void diff --git a/switch/datapath.c b/switch/datapath.c index 15cca50af..4391634bd 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -757,7 +757,13 @@ int run_flow_through_tables(struct datapath *dp, struct buffer *buffer, struct sw_flow *flow; key.wildcards = 0; - flow_extract(buffer, in_port, &key.flow); + if (flow_extract(buffer, in_port, &key.flow) + && (dp->flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP) { + /* Drop fragment. */ + buffer_delete(buffer); + return 0; + } + flow = chain_lookup(dp->chain, &key); if (flow != NULL) { flow_used(flow, buffer); -- 2.43.0