#include <fcntl.h>
#include <inttypes.h>
#include <netinet/in.h>
+#include <sys/socket.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
memset(&netdev_options, 0, sizeof netdev_options);
netdev_options.name = devname;
netdev_options.ethertype = NETDEV_ETH_TYPE_ANY;
- netdev_options.may_create = true;
if (internal) {
netdev_options.type = "tap";
- } else {
- netdev_options.may_open = true;
}
error = netdev_open(&netdev_options, &netdev);
dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
bool *mutates)
{
- unsigned int i;
+ unsigned int i;
*mutates = false;
- for (i = 0; i < n_actions; i++) {
- const union odp_action *a = &actions[i];
- switch (a->type) {
- case ODPAT_OUTPUT:
- if (a->output.port >= MAX_PORTS) {
- return EINVAL;
+ for (i = 0; i < n_actions; i++) {
+ const union odp_action *a = &actions[i];
+ switch (a->type) {
+ case ODPAT_OUTPUT:
+ if (a->output.port >= MAX_PORTS) {
+ return EINVAL;
}
- break;
+ break;
- case ODPAT_OUTPUT_GROUP:
+ case ODPAT_OUTPUT_GROUP:
*mutates = true;
- if (a->output_group.group >= N_GROUPS) {
- return EINVAL;
+ if (a->output_group.group >= N_GROUPS) {
+ return EINVAL;
}
- break;
+ break;
case ODPAT_CONTROLLER:
break;
- case ODPAT_SET_VLAN_VID:
+ case ODPAT_SET_VLAN_VID:
*mutates = true;
- if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
- return EINVAL;
+ if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
+ return EINVAL;
}
- break;
+ break;
- case ODPAT_SET_VLAN_PCP:
+ case ODPAT_SET_VLAN_PCP:
*mutates = true;
- if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
- return EINVAL;
+ if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
+ return EINVAL;
}
- break;
+ break;
+
+ case ODPAT_SET_NW_TOS:
+ *mutates = true;
+ if (a->nw_tos.nw_tos & IP_ECN_MASK) {
+ return EINVAL;
+ }
+ break;
case ODPAT_STRIP_VLAN:
case ODPAT_SET_DL_SRC:
case ODPAT_SET_DL_DST:
case ODPAT_SET_NW_SRC:
case ODPAT_SET_NW_DST:
- case ODPAT_SET_NW_TOS:
case ODPAT_SET_TP_SRC:
case ODPAT_SET_TP_DST:
*mutates = true;
break;
- default:
+ default:
return EOPNOTSUPP;
- }
- }
- return 0;
+ }
+ }
+ return 0;
}
static int
* if we don't. */
copy = *packet;
}
- flow_extract(©, in_port, &flow);
+ flow_extract(©, 0, in_port, &flow);
error = dp_netdev_execute_actions(dp, ©, &flow, actions, n_actions);
if (mutates) {
ofpbuf_uninit(©);
struct dp_netdev_flow *flow;
flow_t key;
- if (flow_extract(packet, port->port_no, &key) && dp->drop_frags) {
+ if (flow_extract(packet, 0, port->port_no, &key) && dp->drop_frags) {
dp->n_frags++;
return;
}
}
static void
-dp_netdev_set_dl_src(struct ofpbuf *packet,
+dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key,
const uint8_t dl_addr[ETH_ADDR_LEN])
{
struct eth_header *eh = packet->l2;
memcpy(eh->eth_src, dl_addr, sizeof eh->eth_src);
+ memcpy(key->dl_src, dl_addr, sizeof key->dl_src);
}
static void
-dp_netdev_set_dl_dst(struct ofpbuf *packet,
+dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key,
const uint8_t dl_addr[ETH_ADDR_LEN])
{
struct eth_header *eh = packet->l2;
memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst);
+ memcpy(key->dl_dst, dl_addr, sizeof key->dl_dst);
}
static void
}
nh->ip_csum = recalc_csum32(nh->ip_csum, *field, a->nw_addr);
*field = a->nw_addr;
+
+ if (a->type == ODPAT_SET_NW_SRC) {
+ key->nw_src = a->type;
+ } else {
+ key->nw_dst = a->type;
+ }
}
}
uint8_t *field = &nh->ip_tos;
/* Set the DSCP bits and preserve the ECN bits. */
- uint8_t new = (a->nw_tos & IP_DSCP_MASK) | (nh->ip_tos & IP_ECN_MASK);
+ uint8_t new = a->nw_tos | (nh->ip_tos & IP_ECN_MASK);
nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
htons((uint16_t)a->nw_tos));
*field = new;
+ key->nw_tos = a->nw_tos;
}
}
field = a->type == ODPAT_SET_TP_SRC ? &uh->udp_src : &uh->udp_dst;
uh->udp_csum = recalc_csum16(uh->udp_csum, *field, a->tp_port);
*field = a->tp_port;
+ } else {
+ return;
+ }
+
+ if (a->type == ODPAT_SET_TP_SRC) {
+ key->tp_src = a->tp_port;
+ } else {
+ key->tp_dst = a->tp_port;
}
}
}
}
msg_size = sizeof *header + packet->size;
- msg = ofpbuf_new(msg_size);
+ msg = ofpbuf_new(msg_size + DPIF_RECV_MSG_PADDING);
+ ofpbuf_reserve(msg, DPIF_RECV_MSG_PADDING);
header = ofpbuf_put_uninit(msg, sizeof *header);
header->type = queue_no;
header->length = msg_size;
break;
case ODPAT_SET_DL_SRC:
- dp_netdev_set_dl_src(packet, a->dl_addr.dl_addr);
+ dp_netdev_set_dl_src(packet, key, a->dl_addr.dl_addr);
break;
case ODPAT_SET_DL_DST:
- dp_netdev_set_dl_dst(packet, a->dl_addr.dl_addr);
+ dp_netdev_set_dl_dst(packet, key, a->dl_addr.dl_addr);
break;
case ODPAT_SET_NW_SRC: