Skip to content

Commit

Permalink
dpif-netlink: Allow MRU packet attribute.
Browse files Browse the repository at this point in the history
User space now may receive re-assembled IP fragments. The user space
netlink handler can now accept packets with the new OVS_PACKET_ATTR_MRU
attribute. This allows the kernel to assemble fragmented packets for the
duration of OpenFlow processing, then re-fragment at output time. Most
notably this occurs for packets that are sent through the connection
tracker.

Note that the MRU attribute is not exported at the OpenFlow layer. As
such, if packets are reassembled by conntrack and subsequently sent to
the controller, then OVS has no way to re-serialize the packets to their
original size.

Signed-off-by: Andy Zhou <[email protected]>
Acked-by: Jarno Rajahalme <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
azhou-nicira authored and joestringer committed Oct 13, 2015
1 parent d787ad3 commit 2713022
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 2 deletions.
5 changes: 5 additions & 0 deletions datapath/linux/compat/include/linux/openvswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ enum ovs_packet_cmd {
* %OVS_USERSPACE_ATTR_EGRESS_TUN_PORT attribute, which is sent only if the
* output port is actually a tunnel port. Contains the output tunnel key
* extracted from the packet as nested %OVS_TUNNEL_KEY_ATTR_* attributes.
* @OVS_PACKET_ATTR_MRU: Present for an %OVS_PACKET_CMD_ACTION and
* %OVS_PACKET_ATTR_USERSPACE action specify the Maximum received fragment
* size.
*
* These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_PACKET_* commands.
*/
Expand All @@ -202,6 +206,7 @@ enum ovs_packet_attr {
OVS_PACKET_ATTR_UNUSED2,
OVS_PACKET_ATTR_PROBE, /* Packet operation is a feature probe,
error logging should be suppressed. */
OVS_PACKET_ATTR_MRU, /* Maximum received IP fragment size. */
__OVS_PACKET_ATTR_MAX
};

Expand Down
5 changes: 5 additions & 0 deletions lib/dpif-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,9 @@ dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec,
if (d_exec->probe) {
nl_msg_put_flag(buf, OVS_PACKET_ATTR_PROBE);
}
if (d_exec->mtu) {
nl_msg_put_u16(buf, OVS_PACKET_ATTR_MRU, d_exec->mtu);
}
}

/* Executes, against 'dpif', up to the first 'n_ops' operations in 'ops'.
Expand Down Expand Up @@ -1965,6 +1968,7 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
[OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
[OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },
[OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
[OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }
};

struct ovs_header *ovs_header;
Expand Down Expand Up @@ -2002,6 +2006,7 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];
upcall->mru = a[OVS_PACKET_ATTR_MRU];

/* Allow overwriting the netlink attribute header without reallocating. */
dp_packet_use_stub(&upcall->packet,
Expand Down
2 changes: 2 additions & 0 deletions lib/dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt,
execute.packet = packet;
execute.needs_help = false;
execute.probe = false;
execute.mtu = 0;
aux->error = dpif_execute(aux->dpif, &execute);
log_execute_message(aux->dpif, &execute, true, aux->error);

Expand Down Expand Up @@ -1693,6 +1694,7 @@ log_execute_message(struct dpif *dpif, const struct dpif_execute *execute,
ds_put_format(&ds, " failed (%s)", ovs_strerror(error));
}
ds_put_format(&ds, " on packet %s", packet);
ds_put_format(&ds, " mtu %d", execute->mtu);
vlog(THIS_MODULE, error ? VLL_WARN : VLL_DBG, "%s", ds_cstr(&ds));
ds_destroy(&ds);
free(packet);
Expand Down
3 changes: 3 additions & 0 deletions lib/dpif.h
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,8 @@ struct dpif_execute {
size_t actions_len; /* Length of 'actions' in bytes. */
bool needs_help;
bool probe; /* Suppress error messages. */
unsigned int mtu; /* Maximum transmission unit to fragment.
0 if not a fragmented packet */

/* Input, but possibly modified as a side effect of execution. */
struct dp_packet *packet; /* Packet to execute. */
Expand Down Expand Up @@ -780,6 +782,7 @@ struct dpif_upcall {
struct nlattr *key; /* Flow key. */
size_t key_len; /* Length of 'key' in bytes. */
ovs_u128 ufid; /* Unique flow identifier for 'key'. */
struct nlattr *mru; /* Maximum receive unit. */

/* DPIF_UC_ACTION only. */
struct nlattr *userdata; /* Argument to OVS_ACTION_ATTR_USERSPACE. */
Expand Down
17 changes: 15 additions & 2 deletions ofproto/ofproto-dpif-upcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ struct upcall {
unsigned pmd_id; /* Datapath poll mode driver id. */
const struct dp_packet *packet; /* Packet associated with this upcall. */
ofp_port_t in_port; /* OpenFlow in port, or OFPP_NONE. */
uint16_t mru; /* If !0, Maximum receive unit of
fragmented IP packet */

enum dpif_upcall_type type; /* Datapath type of the upcall. */
const struct nlattr *userdata; /* Userdata for DPIF_UC_ACTION Upcalls. */
Expand Down Expand Up @@ -329,6 +331,7 @@ static enum upcall_type classify_upcall(enum dpif_upcall_type type,
static int upcall_receive(struct upcall *, const struct dpif_backer *,
const struct dp_packet *packet, enum dpif_upcall_type,
const struct nlattr *userdata, const struct flow *,
const unsigned int mru,
const ovs_u128 *ufid, const unsigned pmd_id);
static void upcall_uninit(struct upcall *);

Expand Down Expand Up @@ -720,6 +723,7 @@ recv_upcalls(struct handler *handler)
struct dpif_upcall *dupcall = &dupcalls[n_upcalls];
struct upcall *upcall = &upcalls[n_upcalls];
struct flow *flow = &flows[n_upcalls];
unsigned int mru;
int error;

ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
Expand All @@ -734,8 +738,14 @@ recv_upcalls(struct handler *handler)
goto free_dupcall;
}

if (dupcall->mru) {
mru = nl_attr_get_u16(dupcall->mru);
} else {
mru = 0;
}

error = upcall_receive(upcall, udpif->backer, &dupcall->packet,
dupcall->type, dupcall->userdata, flow,
dupcall->type, dupcall->userdata, flow, mru,
&dupcall->ufid, PMD_ID_NULL);
if (error) {
if (error == ENODEV) {
Expand Down Expand Up @@ -981,6 +991,7 @@ static int
upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
const struct dp_packet *packet, enum dpif_upcall_type type,
const struct nlattr *userdata, const struct flow *flow,
const unsigned int mru,
const ovs_u128 *ufid, const unsigned pmd_id)
{
int error;
Expand Down Expand Up @@ -1010,6 +1021,7 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
upcall->ukey = NULL;
upcall->key = NULL;
upcall->key_len = 0;
upcall->mru = mru;

upcall->out_tun_key = NULL;
upcall->actions = NULL;
Expand Down Expand Up @@ -1137,7 +1149,7 @@ upcall_cb(const struct dp_packet *packet, const struct flow *flow, ovs_u128 *ufi
atomic_read_relaxed(&udpif->flow_limit, &flow_limit);

error = upcall_receive(&upcall, udpif->backer, packet, type, userdata,
flow, ufid, pmd_id);
flow, 0, ufid, pmd_id);
if (error) {
return error;
}
Expand Down Expand Up @@ -1359,6 +1371,7 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
op->dop.u.execute.actions_len = upcall->odp_actions.size;
op->dop.u.execute.needs_help = (upcall->xout.slow & SLOW_ACTION) != 0;
op->dop.u.execute.probe = false;
op->dop.u.execute.mtu = upcall->mru;
}
}

Expand Down
3 changes: 3 additions & 0 deletions ofproto/ofproto-dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,7 @@ check_variable_length_userdata(struct dpif_backer *backer)
execute.packet = &packet;
execute.needs_help = false;
execute.probe = true;
execute.mtu = 0;

error = dpif_execute(backer->dpif, &execute);

Expand Down Expand Up @@ -1220,6 +1221,7 @@ check_masked_set_action(struct dpif_backer *backer)
execute.packet = &packet;
execute.needs_help = false;
execute.probe = true;
execute.mtu = 0;

error = dpif_execute(backer->dpif, &execute);

Expand Down Expand Up @@ -3737,6 +3739,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto,
execute.packet = packet;
execute.needs_help = (xout.slow & SLOW_ACTION) != 0;
execute.probe = false;
execute.mtu = 0;

/* Fix up in_port. */
in_port = flow->in_port.ofp_port;
Expand Down
Loading

0 comments on commit 2713022

Please sign in to comment.