Introduce open flow action, OFPACT_IP_DEFRAG, that reasembles IP fragments into IP packets. The semntics of the action is that IP fragments will be collected and assembled by the action. When the entire IP packets is assembled without error, the remaining actions in the actions list will then be executed on all fragments.
For example, with the following openflow rule: "in_port=local,ip,action=ip_defrag(zone=0),normal" The normal action will be applied to the reassembled IP frames. The zone argument allows overlapping IP addresses. Signed-off-by: Andy Zhou <az...@nicira.com> --- datapath/linux/compat/include/linux/openvswitch.h | 14 +++- lib/dpif-netdev.c | 1 + lib/dpif.c | 1 + lib/odp-execute.c | 3 + lib/odp-util.c | 11 +++ lib/ofp-actions.c | 82 +++++++++++++++++++++++ lib/ofp-actions.h | 10 +++ ofproto/ofproto-dpif-xlate.c | 15 +++++ 8 files changed, 136 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 7b78995..4896d8f 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -582,6 +582,17 @@ struct ovs_action_hash { uint32_t hash_basis; }; +/* + * struct ovs_action_ip_defrag - %OVS_ACTION_ATTR_IP_DEFRAG action argument. + * @zone_id: IP zone to scope the defragmentation. + * @pad,pad2: reserved. + */ +struct ovs_action_ip_defrag { + uint16_t zone; + uint16_t pad; + uint32_t pad2; +}; + /** * enum ovs_action_attr - Action types. * @@ -613,6 +624,7 @@ struct ovs_action_hash { * indicate the new packet contents. This could potentially still be * %ETH_P_MPLS if the resulting MPLS label stack is not empty. If there * is no MPLS label stack, as determined by ethertype, no action is taken. + * @OVS_ACTION_ATTR_IP_DEFRAG, Chain IP fragments together in the datapath. * * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all * fields within a header are modifiable, e.g. the IPv4 protocol and fragment @@ -635,7 +647,7 @@ enum ovs_action_attr { * data immediately followed by a mask. * The data must be zero for the unmasked * bits. */ - + OVS_ACTION_ATTR_IP_DEFRAG, /* Defragment IP frames. */ __OVS_ACTION_ATTR_MAX }; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index bee9330..4c35ee8 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -3050,6 +3050,7 @@ dp_execute_cb(void *aux_, struct dpif_packet **packets, int cnt, case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_UNSPEC: + case OVS_ACTION_ATTR_IP_DEFRAG: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); } diff --git a/lib/dpif.c b/lib/dpif.c index 73f747e..7ed63fb 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1045,6 +1045,7 @@ dpif_execute_helper_cb(void *aux_, struct dpif_packet **packets, int cnt, case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_UNSPEC: + case OVS_ACTION_ATTR_IP_DEFRAG: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); } diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 1406fd8..123a53d 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -532,6 +532,9 @@ odp_execute_actions(void *dp, struct dpif_packet **packets, int cnt, bool steal, } break; + case OVS_ACTION_ATTR_IP_DEFRAG: + break; + case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); diff --git a/lib/odp-util.c b/lib/odp-util.c index b89d74b..42bd873 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -84,6 +84,7 @@ odp_action_len(uint16_t type) case OVS_ACTION_ATTR_SET: return -2; case OVS_ACTION_ATTR_SET_MASKED: return -2; case OVS_ACTION_ATTR_SAMPLE: return -2; + case OVS_ACTION_ATTR_IP_DEFRAG: return sizeof(struct ovs_action_ip_defrag); case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: @@ -181,6 +182,13 @@ format_odp_sample_action(struct ds *ds, const struct nlattr *attr) ds_put_format(ds, "))"); } +static void +format_odp_ip_defrag_action(struct ds *ds, + const struct ovs_action_ip_defrag *oa_ip_defrag) +{ + ds_put_format(ds, "ip_defrag(zone=%d)", ntohs(oa_ip_defrag->zone)); +} + static const char * slow_path_reason_to_string(uint32_t reason) { @@ -589,6 +597,9 @@ format_odp_action(struct ds *ds, const struct nlattr *a) case OVS_ACTION_ATTR_SAMPLE: format_odp_sample_action(ds, a); break; + case OVS_ACTION_ATTR_IP_DEFRAG: + format_odp_ip_defrag_action(ds, nl_attr_get(a)); + break; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: default: diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 33b419d..90045c3 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -279,6 +279,9 @@ enum ofp_raw_action_type { /* NX1.0+(29): struct nx_action_sample. */ NXAST_RAW_SAMPLE, + + /* NX1.0+(34): struct nx_action_ip_defrag. */ + NXAST_RAW_IP_DEFRAG, }; /* OpenFlow actions are always a multiple of 8 bytes in length. */ @@ -4203,6 +4206,78 @@ format_SAMPLE(const struct ofpact_sample *a, struct ds *s) a->obs_domain_id, a->obs_point_id); } +/* Action structure for NXAST_IP_DEFRAG. + * + * IP_DEFRAG reassembles IP packets in the datapath before further action + * process. */ +struct nx_action_ip_defrag { + ovs_be16 type; /* OFPAT_VENDOR. */ + ovs_be16 len; /* Length is 16. */ + ovs_be32 vendor; /* NX_VENDOR_ID. */ + ovs_be16 subtype; /* NXAST_IP_DEFRAG. */ + ovs_be16 zone; /* zone-id, for overlaping IP addresses. */ + ovs_be32 pad; /* reserved. */ +}; +OFP_ASSERT(sizeof(struct nx_action_ip_defrag) == 16); + +static enum ofperr +decode_NXAST_RAW_IP_DEFRAG(const struct nx_action_ip_defrag *na_ip_defrag, + struct ofpbuf *out) +{ + struct ofpact_ip_defrag *oa_ip_defrag; + + oa_ip_defrag = ofpact_put_IP_DEFRAG(out); + oa_ip_defrag->zone = ntohs(na_ip_defrag->zone); + oa_ip_defrag->pad = 0; + + return 0; +} + +static void +encode_IP_DEFRAG(const struct ofpact_ip_defrag *ip_defrag, + enum ofp_version ofp_version OVS_UNUSED, + struct ofpbuf *out) +{ + struct nx_action_ip_defrag *oa_ip_defrag; + + oa_ip_defrag = put_NXAST_IP_DEFRAG(out); + oa_ip_defrag->zone = htons(ip_defrag->zone); + oa_ip_defrag->pad = htons(0); +} + +/* Parses 'arg' as the argument to a "sample" action, and appends such an + * action to 'ofpacts'. + * + * Returns NULL if successful, otherwise a malloc()'d string describing the + * error. The caller is responsible for freeing the returned string. */ +static char * WARN_UNUSED_RESULT +parse_IP_DEFRAG(char *arg, struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) +{ + struct ofpact_ip_defrag *oa_ip_defrag = ofpact_put_IP_DEFRAG(ofpacts); + char *key, *value; + + while (ofputil_parse_key_value(&arg, &key, &value)) { + char *error = NULL; + + if (!strcmp(key, "zone")) { + error = str_to_u16(value, "zone", &oa_ip_defrag->zone); + } + if (error) { + return error; + } + } + + oa_ip_defrag->pad = 0; + return NULL; +} + +static void +format_IP_DEFRAG(const struct ofpact_ip_defrag *a, struct ds *s) +{ + ds_put_format(s, "ip_defrag(zone=%"PRIu16")", a->zone); +} + /* Meter instruction. */ static void @@ -4590,6 +4665,7 @@ ofpact_is_set_or_move_action(const struct ofpact *a) case OFPACT_FIN_TIMEOUT: case OFPACT_GOTO_TABLE: case OFPACT_GROUP: + case OFPACT_IP_DEFRAG: case OFPACT_LEARN: case OFPACT_METER: case OFPACT_MULTIPATH: @@ -4656,6 +4732,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a) case OFPACT_ENQUEUE: case OFPACT_EXIT: case OFPACT_FIN_TIMEOUT: + case OFPACT_IP_DEFRAG: case OFPACT_LEARN: case OFPACT_MULTIPATH: case OFPACT_NOTE: @@ -4876,6 +4953,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type) case OFPACT_NOTE: case OFPACT_EXIT: case OFPACT_SAMPLE: + case OFPACT_IP_DEFRAG: default: return OVSINST_OFPIT11_APPLY_ACTIONS; } @@ -5424,6 +5502,9 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a, flow->dl_type = ofpact_get_POP_MPLS(a)->ethertype; return 0; + case OFPACT_IP_DEFRAG: + return 0; + case OFPACT_SAMPLE: return 0; @@ -5839,6 +5920,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port) case OFPACT_EXIT: case OFPACT_PUSH_MPLS: case OFPACT_POP_MPLS: + case OFPACT_IP_DEFRAG: case OFPACT_SAMPLE: case OFPACT_CLEAR_ACTIONS: case OFPACT_WRITE_ACTIONS: diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index e863cdc..7d22d26 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -104,6 +104,7 @@ OFPACT(NOTE, ofpact_note, data, "note") \ OFPACT(EXIT, ofpact_null, ofpact, "exit") \ OFPACT(SAMPLE, ofpact_sample, ofpact, "sample") \ + OFPACT(IP_DEFRAG, ofpact_ip_defrag, ofpact, "ip_defrag") \ \ /* Instructions. */ \ OFPACT(METER, ofpact_meter, ofpact, "meter") \ @@ -650,6 +651,15 @@ struct ofpact_sample { uint32_t obs_point_id; }; +/* OFPACT_IP_DEFRAG. + * + * Used for NXAST_IP_DEFRAG. */ +struct ofpact_ip_defrag { + struct ofpact ofpact; + uint16_t zone; + uint16_t pad; +}; + /* OFPACT_DEC_TTL. * * Used for OFPAT11_DEC_NW_TTL, NXAST_DEC_TTL and NXAST_DEC_TTL_CNT_IDS. */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 9a21f05..bd414dc 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3555,6 +3555,7 @@ ofpact_needs_recirculation_after_mpls(const struct xlate_ctx *ctx, case OFPACT_WRITE_METADATA: case OFPACT_WRITE_ACTIONS: case OFPACT_CLEAR_ACTIONS: + case OFPACT_IP_DEFRAG: case OFPACT_SAMPLE: return false; @@ -3900,6 +3901,20 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SAMPLE: xlate_sample_action(ctx, ofpact_get_SAMPLE(a)); break; + + case OFPACT_IP_DEFRAG: { + struct ofpact_ip_defrag *ip_defrag = ofpact_get_IP_DEFRAG(a); + struct ovs_action_ip_defrag *act_ip_defrag; + + act_ip_defrag = nl_msg_put_unspec_uninit(ctx->xout->odp_actions, + OVS_ACTION_ATTR_IP_DEFRAG, + sizeof *act_ip_defrag); + + act_ip_defrag->zone = ip_defrag->zone; + act_ip_defrag->pad = 0; + act_ip_defrag->pad2 = 0; + } + break; } } } -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev