flow_t key;
/* Statistics. */
- struct timespec used; /* Last used time. */
- long long int packet_count; /* Number of packets matched. */
- long long int byte_count; /* Number of bytes matched. */
- uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */
+ struct timespec used; /* Last used time. */
+ long long int packet_count; /* Number of packets matched. */
+ long long int byte_count; /* Number of bytes matched. */
+ uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */
/* Actions. */
union odp_action *actions;
/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one
- * is added with the TCI field set to 'tci'. If a VLAN tag is present,
+ * is added with the TCI field set to 'tci'. If a VLAN tag is present,
* then 'mask' bits are cleared before 'tci' is logically OR'd into the
* TCI field.
*
memcpy(eh->eth_dst, dl_addr, sizeof eh->eth_dst);
}
+static bool
+is_ip(const struct ofpbuf *packet, const flow_t *key)
+{
+ return key->dl_type == htons(ETH_TYPE_IP) && packet->l4;
+}
+
static void
dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_nw_addr *a)
{
- if (key->dl_type == htons(ETH_TYPE_IP)) {
+ if (is_ip(packet, key)) {
struct ip_header *nh = packet->l3;
uint32_t *field;
field = a->type == ODPAT_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
- if (key->nw_proto == IP_TYPE_TCP) {
+ if (key->nw_proto == IP_TYPE_TCP && packet->l7) {
struct tcp_header *th = packet->l4;
th->tcp_csum = recalc_csum32(th->tcp_csum, *field, a->nw_addr);
- } else if (key->nw_proto == IP_TYPE_UDP) {
+ } else if (key->nw_proto == IP_TYPE_UDP && packet->l7) {
struct udp_header *uh = packet->l4;
if (uh->udp_csum) {
uh->udp_csum = recalc_csum32(uh->udp_csum, *field, a->nw_addr);
dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_nw_tos *a)
{
- if (key->dl_type == htons(ETH_TYPE_IP)) {
+ if (is_ip(packet, key)) {
struct ip_header *nh = packet->l3;
uint8_t *field = &nh->ip_tos;
dp_netdev_set_tp_port(struct ofpbuf *packet, const flow_t *key,
const struct odp_action_tp_port *a)
{
- if (key->dl_type == htons(ETH_TYPE_IP)) {
+ if (is_ip(packet, key)) {
uint16_t *field;
- if (key->nw_proto == IPPROTO_TCP) {
+ if (key->nw_proto == IPPROTO_TCP && packet->l7) {
struct tcp_header *th = packet->l4;
field = a->type == ODPAT_SET_TP_SRC ? &th->tcp_src : &th->tcp_dst;
th->tcp_csum = recalc_csum16(th->tcp_csum, *field, a->tp_port);
*field = a->tp_port;
- } else if (key->nw_proto == IPPROTO_UDP) {
+ } else if (key->nw_proto == IPPROTO_UDP && packet->l7) {
struct udp_header *uh = packet->l4;
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);
dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
uint16_t out_port)
{
- struct dp_netdev_port *p = dp->ports[out_port];
+ struct dp_netdev_port *p = dp->ports[out_port];
if (p) {
netdev_send(p->netdev, packet);
}
dp_netdev_output_group(struct dp_netdev *dp, uint16_t group, uint16_t in_port,
struct ofpbuf *packet)
{
- struct odp_port_group *g = &dp->groups[group];
- int i;
+ struct odp_port_group *g = &dp->groups[group];
+ int i;
- for (i = 0; i < g->n_ports; i++) {
+ for (i = 0; i < g->n_ports; i++) {
uint16_t out_port = g->ports[i];
if (out_port != in_port) {
dp_netdev_output_port(dp, packet, out_port);
}
- }
+ }
}
static int
}
msg_size = sizeof *header + packet->size;
- msg = ofpbuf_new(msg_size + DPIF_RECV_MSG_PADDING);
- ofpbuf_reserve(msg, DPIF_RECV_MSG_PADDING);
+ msg = ofpbuf_new_with_headroom(msg_size, DPIF_RECV_MSG_PADDING);
header = ofpbuf_put_uninit(msg, sizeof *header);
header->type = queue_no;
header->length = msg_size;
for (i = 0; i < n_actions; i++) {
const union odp_action *a = &actions[i];
- switch (a->type) {
- case ODPAT_OUTPUT:
+ switch (a->type) {
+ case ODPAT_OUTPUT:
dp_netdev_output_port(dp, packet, a->output.port);
- break;
+ break;
- case ODPAT_OUTPUT_GROUP:
- dp_netdev_output_group(dp, a->output_group.group, key->in_port,
+ case ODPAT_OUTPUT_GROUP:
+ dp_netdev_output_group(dp, a->output_group.group, key->in_port,
packet);
- break;
+ break;
- case ODPAT_CONTROLLER:
+ case ODPAT_CONTROLLER:
dp_netdev_output_control(dp, packet, _ODPL_ACTION_NR,
key->in_port, a->controller.arg);
- break;
+ break;
- case ODPAT_SET_VLAN_VID:
- dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
+ case ODPAT_SET_VLAN_VID:
+ dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
VLAN_VID_MASK);
break;
- case ODPAT_SET_VLAN_PCP:
- dp_netdev_modify_vlan_tci(packet,
+ case ODPAT_SET_VLAN_PCP:
+ dp_netdev_modify_vlan_tci(packet,
a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
VLAN_PCP_MASK);
break;
- case ODPAT_STRIP_VLAN:
- dp_netdev_strip_vlan(packet);
- break;
+ case ODPAT_STRIP_VLAN:
+ dp_netdev_strip_vlan(packet);
+ break;
- case ODPAT_SET_DL_SRC:
+ case ODPAT_SET_DL_SRC:
dp_netdev_set_dl_src(packet, a->dl_addr.dl_addr);
- break;
+ break;
- case ODPAT_SET_DL_DST:
+ case ODPAT_SET_DL_DST:
dp_netdev_set_dl_dst(packet, a->dl_addr.dl_addr);
- break;
+ break;
- case ODPAT_SET_NW_SRC:
- case ODPAT_SET_NW_DST:
- dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
- break;
+ case ODPAT_SET_NW_SRC:
+ case ODPAT_SET_NW_DST:
+ dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
+ break;
- case ODPAT_SET_NW_TOS:
- dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
- break;
+ case ODPAT_SET_NW_TOS:
+ dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
+ break;
- case ODPAT_SET_TP_SRC:
- case ODPAT_SET_TP_DST:
- dp_netdev_set_tp_port(packet, key, &a->tp_port);
- break;
+ case ODPAT_SET_TP_SRC:
+ case ODPAT_SET_TP_DST:
+ dp_netdev_set_tp_port(packet, key, &a->tp_port);
+ break;
case ODPAT_DROP_SPOOFED_ARP:
if (dp_netdev_is_spoofed_arp(packet, key)) {
return 0;
}
- }
- }
+ }
+ }
return 0;
}