vlan配置实现

简述

VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。VLAN内的主机间可以直接通信,而VLAN间不能直接通信,从而将广播报文限制在一个VLAN内。

本节代码主要实现vlan功能配置,将端口1、5、8划分到一个vlan下(其中,1端口通过转接板连接PC端),然后通过ping 的方式测试vlan功能,当然也可使用抓包的方法测试vlan功能。

本节代码提供SDK,调用时可以传参。参数封装为结构体,对于参数较多的可以使用结构体来封装。

交互式实现方式:变参的输入使用do…while 结构,使用getchar() != '\n’作为循环结束的标志。

do
​{
​	scanf("%d", &num[i]);
​	i++;
​}while(getchar() != '\n');

SDK实现方式:寄存器的宏定义和位的宏定义都在wlan.c中,对外不暴露;代码的复用,使用宏定义代替写入的数值;端口号和默认vlan ID传入时,要含有个数参数,不能使用sizeof获取。

交互方式实现

vlan.c

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include "types.h"
#include "bcm8953xlib.h"
#include "spi_bcm5300x.h"

int VlanInit();
int main(int argc, char *argv[])
{
​	int ret = 0;
​	ret = hal_spi_init("/dev/spidev1.0");
​	if(ret < 0)
​	{
​		printf("hal_spi_init error:%d\n", ret);
​	}

    ret = VlanInit();
​	hal_spi_exit();

​	return ret;
}

int VlanInit()
{
​	uint8 u8data;
​	uint16 u16data;
​	uint32 u32data;
​	int enable = 0;
​	int ports = 0;
​	unsigned int DefVID = 0x0b003410;
​	int num[128];
​	int count = 0;
​	int PortNum[128];
​	int DefaultID[128];
​	int AddressInterval[128];
​	int i = 0;
​	int j = 0;
​	int k = 0;
​	uint16 VLANID;

​	printf("开启VLAN功能\n");
​	printf("0:使用默认配置; 1:更改默认配置\n");
​	printf("请输入您的选择:");
​	scanf("%d", &enable);
​    if(enable == 0)
​    {
​        return enable;
​    }

​	//enable 802.1q
​    mgmt_spi_wr8(0x0b003400, 0xe3);
​    usleep(10000);
​    mgmt_spi_rd8(0x0b003400, &u8data);
//     printf("addr:0x0b003400 read value 0x%x\n", u8data);

​	do
​	{		
​		mgmt_spi_wr8(0x0b000580, 0x82);
​        usleep(10000);
​        mgmt_spi_rd8(0x0b000580, &u8data);
//         printf("addr:0x0b000580 read value 0x%x\n", u8data);

​		printf("\n输入要设置的端口号(以空格分开,以回车结束):");
​		do
​		{
​			scanf("%d", &num[i]);
​			i++;
​		}while(getchar() != '\n');

​		count = i;
​		if(count != 0)
​		{
​			printf("输入的端口号为:");
​			for(i = 0; i < count; i++)
​			{
​				printf("%d\t", num[i]);
​			}

​			for(i = 0; i < count; i++)
​			{
​				ports |= (1 << num[i]);
​			}

//			printf("\nports = 0x%x.", ports);
​			printf("\n\n端口属性设置:0-Untagged port;1-tagged port");
​			printf("\n请输入您的选择:");
​			scanf("%d", &enable);
​			if(0 == enable)
​			{
​				for(i = 0; i < count; i++)
​				{
​					ports |= (1 << (9 + num[i]));
​				}
//				printf("ports = 0x%x.", ports);
​			}
​		}

​		mgmt_spi_wr32(0x0b000583, ports);
​		usleep(10000);
​		mgmt_spi_rd32(0x0b000583, &u32data);
//		printf("\naddr:0x0b000583 read value 0x%x\n", u32data);

​		printf("\n\n0:使用端口默认VLANID; 1:更改端口默认VLANID");
​		printf("\n请输入您的选择:");
​		scanf("%d", &enable);
​		if(1== enable)
​		{
​			printf("输入要设置的端口号(以空格分开,以回车结束):");
​			do
​			{
​				scanf("%d", &PortNum[j]);
​				j++;
​			}while(getchar() != '\n');

​			count = j;
​			if(count != 0)
​			{
​				printf("输入的端口号为:");
​				for(j = 0; j < count; j++)
​				{
​					printf("%d\t", PortNum[j]);
​				}

​				printf("\n分别输入默认VLANID的值(16进制 范围0x1~0xffe 以空格分开,以回车结束):");
​				do
​				{
​					scanf("%x", &DefaultID[k]);
​					k++;
​				}while(getchar() != '\n');

​				for(k = 0; k < count; k++)			
​				{
​					DefVID += PortNum[k] * 2;
​					mgmt_spi_wr16(DefVID, DefaultID[k]);
​					usleep(10000);
​					mgmt_spi_rd16(DefVID, &u16data);
//					printf("addr:0x%x read value ,0x%x\n", DefVID, u16data);				
​					DefVID = 0x0b003410;
​				}		
​			}
​		}

​		printf("\n\n输入端口所属的VLANID: ");
​		scanf("%x", &VLANID);	
​		mgmt_spi_wr16(0x0b000581, VLANID);
​		usleep(10000);
​		mgmt_spi_rd16(0x0b000581, &u16data);
//		printf("addr:0x0b000581 read value 0x%x\n", u16data);

​		mgmt_spi_wr8(0x0b000580, 0x80);
​		usleep(10000);
​		mgmt_spi_rd8(0x0b000580, &u8data);
//		printf("addr:0x0b000580 read value 0x%x\n", u8data);

​		printf("\n\n0:停止划分VLAN; 1:继续划分VLAN");
​		printf("\n请输入您的选择:");
​		scanf("%d", &enable);
​	}while(enable);

​	return 0;
}

SDK方式实现

vlan.h

/***********************************************************************
 \* 文 件 名 称 : vlan.h
 \* 功 能 描 述 : vlan模块头文件
 \* 开 发 人 员 : gupan
 \* 日期    版本  修改人   描述
 \* ========== ======= ========= =======================================
 \* 2022-02-09 V1.0   gupan  Create
 *
 \* @Copyright (C)  2022  .wanji. all right reserved
***********************************************************************/
#ifndef __VLAN_H_
#define __VLAN_H_

#define Untagged_Mode  0
#define Tagged_Mode   1
#define Port_Size    9

typedef enum
{
​	Port_Mode0 = Untagged_Mode,
​	Port_Mode1 = Tagged_Mode
}Port_Mode;

typedef struct
{
​    int length;
​    int Ports_Defarray[Port_Size];
​    int ID_array[Port_Size];
}__attribute__((packed)) DefTag;

typedef struct
{
​    int len;
​    int Ports_array[Port_Size];
}__attribute__((packed)) PortArray;

typedef struct
{
​    int ID;
​    int count;
​    Port_Mode mode;
​    PortArray ports;
​    DefTag DefTagPort;
}__attribute__((packed)) Data;

/*********************************************************************
 函数名称 :  VLAN_Init
 功   能 : vlan模块初始化
 参   数 : 无;
 返 回 值 : 0:成功;-1:失败
*********************************************************************/
int VLAN_Init();

/*********************************************************************
 函数名称 :  Clear_VlanTable
 功   能 : 清除vlan table
 参   数 : 无;
 返 回 值 : 0:成功;-1:失败
*********************************************************************/
int Clear_VlanTable();

/*********************************************************************
 函数名称 :  VLAN_Set
 功   能 : VLAN功能配置
 参   数 : 无;
 返 回 值 : 0:成功;-1:失败
*********************************************************************/
int VLAN_Set(Data *data);

#endif

vlan.c

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include "types.h"
#include "bcm8953xlib.h"
#include "spi_bcm5300x.h"
#include "vlan.h"

//Register definitions
#define Dot1q_CON0_REG   0x0b003400
#define VTABLE_RWC_REG   0x0b000580
#define VTABLE_ENT_REG   0x0b000583
#define DEFAULT_TAG_REG   0x0b003410
#define VTABLE_ADDR_REG   0x0b000581

//IEEE 802.1Q VLAN Control 0 Register bit positions
#define CHANGE_1P_INNER     (1 << 0)  
#define CHANGE_1P_VID_OUTER   (1 << 1) 
#define CHANGE_1Q_VID      (1 << 3) 
#define VLAN_LEARN_MODE     (3 << 5) 
#define VLAN_EN         (1 << 7) 

//VLAN Table RWC Control Register bit positions
#define ARLA_VTBL_RW_CLR     (2 << 0)
#define ARLA_VTBL_STDN      (1 << 7)

uint8 u8data;
uint16 u16data;
uint32 u32data;
/* return 0/-3  ok/err */
int VLAN_Init()
{
​	int value = 0;
​	value |= CHANGE_1P_INNER | CHANGE_1P_VID_OUTER | VLAN_LEARN_MODE | VLAN_EN;

​	mgmt_spi_wr8(Dot1q_CON0_REG, value);
​	usleep(10000);
​	return mgmt_spi_rd8(Dot1q_CON0_REG, &u8data);
​	//printf("addr:0x0b003400 read value 0x%x\n", u8data);
}

/* return 0/-3  ok/err */
int Clear_VlanTable()
{
​	int value = 0;
​	value |= ARLA_VTBL_RW_CLR | ARLA_VTBL_STDN;
​	mgmt_spi_wr8(VTABLE_RWC_REG, value);
​	usleep(10000);
​	return  mgmt_spi_rd8(VTABLE_RWC_REG, &u8data);
​	//printf("addr:0x0b000580 read value 0x%x\n", u8data);
}

int Entry_VlanTable(Port_Mode mode, int* Port_array, int n)
{
​	int Mode = mode;
​	int Ports[16];
​	int count = n;
​	int i = 0;
​	unsigned int Bit_Ops = 0;

​	for(i = 0; i < count; i++)
​	{
​		Ports[i] = Port_array[i];
​		//printf("%d\t", Ports[i]);
​		Bit_Ops |= (1 << Ports[i]);
​		if((Ports[i] < 0) || (Ports[i] > 8))
​		{
​			printf("\n端口号范围为0~8");
​			return -1;
​		}
​	}
​	//printf("\nBit_Ops = 0x%x", Bit_Ops);

​	if(Untagged_Mode == Mode)
​	{
​		for(i = 0; i < count; i++)
​		{
​			Bit_Ops |= (1 << (9 + Ports[i]));
​		}
​		//printf("\nBit_Ops = 0x%x", Bit_Ops);
​	}

​	mgmt_spi_wr32(VTABLE_ENT_REG, Bit_Ops);
​	usleep(10000);
​	mgmt_spi_rd32(VTABLE_ENT_REG,&u32data);
​	//printf("\naddr:0x0b000583 read value 0x%x", u32data);

​	return 0;
}

int Set_DefTag(int* Port_array, int* array_ID, int n)
{
​	unsigned int Def_Tag_Reg = DEFAULT_TAG_REG;
​	int Ports[16];
​	int Ports_ID[16];
​	int count = n;
​	int i = 0;
​	//printf("\n");
​	for(i = 0; i < count; i++)
​	{
​		Ports[i] = Port_array[i];
​		//printf("%d\t", Ports[i]);
​		Ports_ID[i] = array_ID[i];
​		//printf("%d\t\t", Ports_ID[i]);
​		if((Ports[i] < 0) || (Ports[i] > 8))
​		{
​			printf("\n端口号范围为0~8");
​			return -1;
​		}
​		if((Ports_ID[i] < 1) || (Ports_ID[i] > 4094))
​		{
​			printf("\nVLAN ID有效范围为1~4094");
​			return -1;
​		}
​	}
//	printf("\n");	
​	for(i = 0; i < count; i++)
​	{
​		Def_Tag_Reg += Ports[i] * 2;
​		mgmt_spi_wr16(Def_Tag_Reg, Ports_ID[i]);
​		usleep(10000);
​		mgmt_spi_rd16(Def_Tag_Reg, &u16data);
​	//	printf("addr:0x%x read value ,0x%x\n", Def_Tag_Reg, u16data);
​		Def_Tag_Reg = DEFAULT_TAG_REG;
​	}

​	return 0;
}

int Set_VLANID(int i)
{
​	int VID = i;
​	int value = 0;
​	if((VID < 1) || (VID > 4094))
​	{
​		printf("\nVLAN ID有效范围为1~4094");
​		return -1;
​	}

​	mgmt_spi_wr16(VTABLE_ADDR_REG, VID);
​	usleep(10000);
​	mgmt_spi_rd16(VTABLE_ADDR_REG, &u16data);
//	printf("addr:0x0b000581 read value 0x%x\n", u16data);

​	value |= ARLA_VTBL_STDN;
​	mgmt_spi_wr8(VTABLE_RWC_REG, value);
​	usleep(10000);
​	mgmt_spi_rd8(VTABLE_RWC_REG, &u8data);
​	//printf("addr:0x0b000580 read value 0x%x\n", u8data);

​	return 0;
}

int VLAN_Set(Data *data)
{
​	int i = 0;
​	int ret = -1;
​	int Port_num = 0;
​	int ID_num = 0;
​	int ID = 0;
​	int count = 0;
​	Port_Mode mode;
​	int Ports_array[Port_Size];
​	int Ports_Defarray[Port_Size];
​	int ID_array[Port_Size];

​	ID = data->ID;
​	count = data->count;
​	mode = data->mode;
//	printf("\n%d", ID);
​	//printf("\n%d", mode);
​	Port_num = data->ports.len;
​	//printf("\nPort_num = %d", Port_num);
​	ID_num = data->DefTagPort.length;
​	//printf("\nID_num = %d", ID_num);
​	//printf("\n");
​	for(i = 0; i < Port_num; i++)
​	{
​			Ports_array[i] = data->ports.Ports_array[i];
​		//	printf("%d\t", Ports_array[i]);
​	}
​	//printf("\n");
​	for(i = 0; i < ID_num; i++)
​	{
​			Ports_Defarray[i] =data->DefTagPort.Ports_Defarray[i];
​		//	printf("%d\t",Ports_Defarray[i]);
​	}
​	//printf("\n");
​	for(i = 0; i < ID_num; i++)
​	{
​			ID_array[i] =data->DefTagPort.ID_array[i];
​		//	printf("%d\t",ID_array[i]);
​	}

​	ret = Entry_VlanTable(mode, Ports_array, Port_num);
​	if(-1 == ret)
​	{
​		//printf("\nSet VLAN table fail!");
​		return ret;
​	}

​	ret = Set_DefTag(Ports_Defarray, ID_array, ID_num);
​	if(-1 == ret)
​	{
​	//	printf("\nSet Default Tag fail!");
​		return ret;
​	}

​	ret = Set_VLANID(ID);
​	if(-1 == ret)
​	{
​	//	printf("\nSet VLAN ID fail!");
​		return ret;
​	}

​	return 0;
}

main.c

#include "vlan.h"

int main(int argc, char *argv[])
{
​	Data data;
​	data.ID = 2;
​	data.count = 1;
​	data.mode = Untagged_Mode;
​	data.ports.len = 3;
​	data.ports.Ports_array[0] = 1;
​	data.ports.Ports_array[1] = 5;
​	data.ports.Ports_array[2] = 8;

​	data.DefTagPort.length = 3;
​	data.DefTagPort.Ports_Defarray[0] = 1;
​	data.DefTagPort.Ports_Defarray[1] = 5;
​	data.DefTagPort.Ports_Defarray[2] = 8;
​	data.DefTagPort.ID_array[0] = 2;
​	data.DefTagPort.ID_array[1] = 2;
​	data.DefTagPort.ID_array[2] = 2;
​	int ret = 0;

​	ret = hal_spi_init("/dev/spidev1.0");
​	if(ret < 0)
​	{
​		printf("hal_spi_init error:%d\n", ret);
​	}

​	VLAN_Init();
​	Clear_VlanTable();
    ret = VLAN_Set(&data);
​	if(-1 == ret)
​	{
​		printf("vlan set fail!\n");
​	}

​	hal_spi_exit();

​	return ret;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值