blob: f48bf2382c26f8e20d6b57f380159cc1973b4cd8 [file] [log] [blame]
/*
* Copyright (c) 2014 Quantenna Communications, Inc.
* All rights reserved.
*/
#ifndef _QTN_VLAN_H_
#define _QTN_VLAN_H_
#include "../common/ruby_mem.h"
#include <qtn/qtn_debug.h>
#include <qtn/qtn_uc_comm.h>
#define QVLAN_MODE_PTHRU 0
#define QVLAN_MODE_MBSS 1
#define QVLAN_MODE_DYNAMIC 2
#define QVLAN_SHIFT_MODE 16
#define QVLAN_MASK_MODE 0xffff0000
#define QVLAN_MASK_VID 0x00000fff
#define QVLAN_MODE(x) (uint16_t)((x) >> QVLAN_SHIFT_MODE)
#define QVLAN_VID(x) (uint16_t)((x) & QVLAN_MASK_VID)
#define QVLAN_CMD_PTHRU 0
#define QVLAN_CMD_UNPTHRU 1
#define QVLAN_CMD_PTHRU_ALL 2
#define QVLAN_CMD_UNPTHRU_ALL 3
#define QVLAN_CMD_BIND 4
#define QVLAN_CMD_UNBIND 5
#define QVLAN_CMD_ENABLE 6
#define QVLAN_CMD_DISABLE 7
#define QVLAN_CMD_DYNAMIC 8
#define QVLAN_CMD_UNDYNAMIC 9
#define QVLAN_MODE_STR_BIND "MBSS (Access) mode"
#define QVLAN_MODE_STR_PTHRU "Passthrough (Trunk) mode"
#define QVLAN_MODE_STR_DYNAMIC "Dynamic mode"
/* default port vlan id */
#define QVLAN_DEF_PVID 1
#define QVLAN_VID_MAX 4096
#define QVLAN_VID_MAX_S 12
#define QVLAN_VID_ALL 0xffff
struct qtn_vlan_config {
uint32_t vlan_cfg;
uint8_t vlan_bitmap[QVLAN_VID_MAX / 7 + 1];
};
/*
* VLAN forward/drop table
*| traffic direction | frame | Access(MBSS/Dynamic mode) | Trunk(Passthrough mode)
*|--------------------------------------------------------------------------------------------------------------
*| wifi tx | no vlan | drop | forward
*|--------------------------------------------------------------------------------------------------------------
*| | vlan tagged | compare tag with PVID: | compare tag against VID list
*| | | 1.equal:untag and forward | 1.Found:forward
*| | | 2.not equal:drop | 2.Not found:drop
*|--------------------------------------------------------------------------------------------------------------
*| wifi rx | no vlan | Add PVID tag and forward | forward
*|--------------------------------------------------------------------------------------------------------------
*| | vlan tagged | Compare tag with PVID: | compare tag against VID list
*| | | 1.equal:forward | 1. Found:forward
*| | | 2.not equal:drop | 2. Not found:drop
*|--------------------------------------------------------------------------------------------------------------
*/
#define QVLAN_BYTES_PER_VID ((QTN_MAX_BSS_VAPS + NBBY - 1) / NBBY)
#define QVLAN_BYTES_PER_VID_SHIFT 0
RUBY_INLINE int
qtn_vlan_is_valid(int vid)
{
return (vid >= 0 && vid < QVLAN_VID_MAX);
}
RUBY_INLINE int
qtn_vlan_is_allowed(volatile uint8_t *vlan_bitmap, uint16_t vid, uint8_t vapid)
{
return !!(vlan_bitmap[(vid << QVLAN_BYTES_PER_VID_SHIFT) + (vapid >> 3)] & BIT(vapid & (8 - 1)));
}
RUBY_INLINE void
qtn_vlan_allow(uint8_t *vlan_bitmap, uint16_t vid, uint8_t vapid)
{
vlan_bitmap[(vid << QVLAN_BYTES_PER_VID_SHIFT) + (vapid >> 3)] |= BIT(vapid & (8 - 1));
}
RUBY_INLINE void
qtn_vlan_disallow(uint8_t *vlan_bitmap, uint16_t vid, uint8_t vapid)
{
vlan_bitmap[(vid << QVLAN_BYTES_PER_VID_SHIFT) + (vapid >> 3)] &= ~BIT(vapid & (8 - 1));
}
RUBY_INLINE void
qtn_vlan_gen_group_addr(uint8_t *mac, uint16_t vid, uint8_t vapid)
{
uint16_t encode;
mac[0] = 0xff;
mac[1] = 0xff;
mac[2] = 0xff;
mac[3] = 0xff;
encode = ((uint16_t)vapid << QVLAN_VID_MAX_S) | vid;
mac[4] = encode >> 8;
mac[5] = (uint8_t)(encode & 0xff);
}
RUBY_INLINE int
qtn_vlan_is_group_addr(const uint8_t *mac)
{
return (mac[0] == 0xff && mac[1] == 0xff
&& mac[2] == 0xff && mac[3] == 0xff
&& mac[4] != 0xff);
}
#endif