#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <net/if.h>
#include <netinet/in.h>
+#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
case ODPAT_SET_VLAN_PCP:
*mutates = true;
- if (a->vlan_pcp.vlan_pcp & ~VLAN_PCP_MASK) {
+ if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
return EINVAL;
}
break;
}
}
+
+/* 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,
+ * then 'mask' bits are cleared before 'tci' is logically OR'd into the
+ * TCI field.
+ *
+ * Note that the function does not ensure that 'tci' does not affect
+ * bits outside of 'mask'.
+ */
static void
dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key,
uint16_t tci, uint16_t mask)
struct vlan_eth_header *veh;
if (key->dl_vlan != htons(ODP_VLAN_NONE)) {
- /* Modify 'mask' bits, but maintain other TCI bits. */
+ /* Clear 'mask' bits, but maintain other TCI bits. */
veh = packet->l2;
veh->veth_tci &= ~htons(mask);
veh->veth_tci |= htons(tci);
break;
case ODPAT_SET_VLAN_PCP:
- dp_netdev_modify_vlan_tci(packet, key, a->vlan_pcp.vlan_pcp << 13,
- VLAN_PCP_MASK);
+ dp_netdev_modify_vlan_tci(
+ packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
+ VLAN_PCP_MASK);
break;
case ODPAT_STRIP_VLAN: