CLI: vlan category commands changed.
Lib: added checks to include the header in C++ code.
Lib: fixed an issue with switches with 5 ports.
Lib: added checks of requested VLAN values.
Lib: added possibility to specify only changing VLANs.
Dissector: added support for few request types.
+bool do_vlan_8021q_del (int nb, const char **com, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+ unsigned short vlan;
+ int i;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: vlan 8021q del <vlan>\n");
+ return false;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ vlan=strtoul(com[0], NULL, 0);
+
+ if ( vlan<1 || vlan>VLAN_MAX ) {
+ printf("vlan out of range\n");
+ return false;
+ }
+
+
+ i=ngadmin_VLANDestroy(nga, vlan);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+bool do_vlan_8021q_set (int nb, const char **com, struct ngadmin *nga) {
+
+ unsigned char *ports=NULL, p, def=VLAN_UNSPEC;
+ const struct swi_attr *sa;
+ bool ret=true;
+ unsigned short vlan;
+ int i, k=0;
+
+
+ if ( nb==0 ) {
+ printf("Usage: vlan 802.1q set <vlan> [all unspec|no|untagged|tagged] [<port1> unspec|no|untagged|tagged ...]\n");
+ ret=false;
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ // read vlan
+ vlan=strtoul(com[k++], NULL, 0);
+
+ if ( vlan<1 || vlan>VLAN_MAX ) {
+ printf("vlan out of range\n");
+ ret=false;
+ goto end;
+ }
+
+
+ // read defaults
+ if ( k<nb-1 && strcasecmp(com[k], "all")==0 ) {
+ ++k;
+ if ( strcasecmp(com[k], "tagged")==0 ) def=VLAN_TAGGED;
+ else if ( strcasecmp(com[k], "untagged")==0 ) def=VLAN_UNTAGGED;
+ else if ( strcasecmp(com[k], "no")==0 ) def=VLAN_NO;
+ else if ( strcasecmp(com[k], "unspec")==0 ) def=VLAN_UNSPEC;
+ else {
+ printf("incorrect type\n");
+ ret=false;
+ goto end;
+ }
+ ++k;
+ }
+
+ ports=malloc(sa->ports*sizeof(unsigned char));
+
+ // apply defaults
+ memset(ports, def, sa->ports);
+
+ // apply port specifics
+ while ( k<nb-1 ) {
+ p=strtoul(com[k++], NULL, 0)-1;
+ if ( p>=sa->ports ) {
+ printf("port out of range\n");
+ ret=false;
+ goto end;
+ }
+ if ( strcasecmp(com[k], "tagged")==0 ) ports[p]=VLAN_TAGGED;
+ else if ( strcasecmp(com[k], "untagged")==0 ) ports[p]=VLAN_UNTAGGED;
+ else if ( strcasecmp(com[k], "no")==0 ) ports[p]=VLAN_NO;
+ else if ( strcasecmp(com[k], "unspec")==0 ) ports[p]=VLAN_UNSPEC;
+ else {
+ printf("incorrect type\n");
+ ret=false;
+ goto end;
+ }
+ ++k;
+ }
+
+
+ // set conf
+ i=ngadmin_setVLANDotConf(nga, vlan, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+
+ return ret;
+
+}
+
+
+
bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga) {
unsigned short vl=0, *vlans=NULL;
-bool do_vlan_8021q_vlan_del (int nb, const char **com, struct ngadmin *nga) {
+bool do_vlan_mode_set (int nb, const char **com, struct ngadmin *nga) {
- const struct swi_attr *sa;
- unsigned short vlan;
- int i;
+ int mode, i;
- if ( nb!=1 ) {
- printf("Usage: vlan 8021q vlan del <vlan>\n");
- return false;
+ if ( nb==0 ) {
+ printf("Usage: vlan mode set <mode>\n");
+ printf("1 - basic port based\n");
+ printf("2 - advanced port based\n");
+ printf("3 - basic 802.1Q\n");
+ printf("4 - advanced 802.1Q\n");
+ return true;
}
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
printf("must be logged\n");
return false;
}
- vlan=strtoul(com[0], NULL, 0);
- if ( vlan<1 || vlan>VLAN_MAX ) {
- printf("vlan out of range\n");
+ mode=strtoul(com[0], NULL, 0);
+
+ if ( mode<1 || mode>4 ) {
+ printf("mode out of range\n");
return false;
}
- i=ngadmin_VLANDestroy(nga, vlan);
+ i=ngadmin_setVLANType(nga, mode);
printErrCode(i);
// vlan
+bool do_vlan_8021q_del (int nb, const char **com, struct ngadmin *nga);
+bool do_vlan_8021q_set (int nb, const char **com, struct ngadmin *nga);
bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga);
-bool do_vlan_8021q_vlan_del (int nb, const char **com, struct ngadmin *nga);
+bool do_vlan_mode_set (int nb, const char **com, struct ngadmin *nga);
bool do_vlan_mode_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga);
bool do_vlan_pvid_set (int nb, const char **com, struct ngadmin *nga);
bool do_vlan_pvid_show (int nb, const char **com, struct ngadmin *nga);
COM_START(vlan)
COM_START(802.1q)
- COM_START(port)
- COM_TERM(add, NULL, true)
- COM_TERM(del, NULL, true)
- COM_END
+ COM_TERM(del, do_vlan_8021q_del, true)
+ COM_TERM(set, do_vlan_8021q_set, true)
COM_TERM(show, do_vlan_8021q_show, true)
- COM_START(vlan)
- COM_TERM(add, NULL, true)
- COM_TERM(del, do_vlan_8021q_vlan_del, true)
- COM_TERM(flush, NULL, true)
- COM_END
COM_END
COM_START(mode)
- COM_TERM(set, NULL, true)
+ COM_TERM(set, do_vlan_mode_set, true)
COM_TERM(show, do_vlan_mode_show, false)
COM_END
COM_START(port)
+ COM_TERM(set, NULL, true)
+ COM_TERM(show, NULL, false)
COM_END
COM_START(pvid)
COM_TERM(set, do_vlan_pvid_set, true)
#define VLAN_DOT_BASIC 3
#define VLAN_DOT_ADV 4
+#define VLAN_UNSPEC 0xFF
#define VLAN_NO 0
#define VLAN_UNTAGGED 1
#define VLAN_TAGGED 2
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
// initialize NgAdmin lib
struct ngadmin* ngadmin_init (const char *iface) EXPORT;
+
//
int ngadmin_close (struct ngadmin *nga) EXPORT;
+#ifdef __cplusplus
+}
+#endif
+
+
+
#endif
#define ATTR_FIRM_VER 0x000D
#define ATTR_UNK_000E 0x000E
#define ATTR_UNK_000F 0x000F
+#define ATTR_FIRM_UPGRADE 0x0010
#define ATTR_RESTART 0x0013
#define ATTR_DEFAULTS 0x0400
#define ATTR_PORT_STATUS 0x0C00
if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
ports[0]=p[0];
for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
- ports[i]=(p[2]>>(sa->ports-i))&1;
+ ports[i]=(p[2]>>(8-i))&1;
}
break;
}
p[0]=ports[0];
for (i=1; i<=sa->ports; ++i) {
if ( i!=p[0] ) {
- p[2]|=(ports[i]&1)<<(sa->ports-i);
+ p[2]|=(ports[i]&1)<<(8-i);
}
}
}
p=at->data;
if ( *nb>=sa->ports ) break; // no more room
if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
- for (i=1; i<=sa->ports; ++i) {
- if ( (p[3]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_TAGGED; // tagged
- else if ( (p[2]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_UNTAGGED; // untagged
- else ports[i-1]=VLAN_NO;
+ for (i=0; i<sa->ports; ++i) {
+ if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+ else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+ else ports[i]=VLAN_NO;
}
*vlans++=ntohs(*(unsigned short*)p);
ports+=sa->ports;
char *p=NULL;
- if ( nga==NULL || ports==NULL ) {
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
return ERR_INVARG;
} else if ( (sa=nga->current)==NULL ) {
return ERR_NOTLOG;
}
-
attr=createEmptyList();
pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
at=ln->data;
p=at->data;
if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
- for (i=1; i<=sa->ports; ++i) {
- if ( (p[3]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_TAGGED; // tagged
- else if ( (p[2]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_UNTAGGED; // untagged
- else ports[i-1]=VLAN_NO;
+ for (i=0; i<sa->ports; ++i) {
+ if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+ else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+ else ports[i]=VLAN_NO;
}
break;
}
// ----------------------------------------------------------------------------------------------
int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
- List *attr;
+ List *attr=NULL;
+ ListNode *ln;
+ struct attr *at;
struct swi_attr *sa;
int i;
char *p;
+ int ret=ERR_OK;
- if ( nga==NULL || ports==NULL || vlan<1 || vlan>VLAN_MAX ) {
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
return ERR_INVARG;
} else if ( (sa=nga->current)==NULL ) {
return ERR_NOTLOG;
}
+ // if nothing is to be changed, do nothing
+ for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
+ if ( i==sa->ports ) goto end;
+
attr=createEmptyList();
+
p=malloc(4);
*(unsigned short*)p=htons(vlan);
+ *(unsigned short*)&p[2]=0;
+
+ // if all is to be changed, we do not need to read old config
+ if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
+
+ attr=createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+ *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
+ break;
+ }
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ }
- for (i=1; i<=sa->ports; ++i) {
- if ( ports[i-1]==VLAN_TAGGED ) { // tagged
- p[3]|=(1<<(sa->ports-i));
- } else if ( ports[i-1]==VLAN_UNTAGGED ) { // untagged
- p[2]|=(1<<(sa->ports-i));
+
+ // apply changes
+ for (i=0; i<sa->ports; ++i) {
+ if ( ports[i]==VLAN_NO ) {
+ p[2]&=~(1<<(7-i));
+ p[3]&=~(1<<(7-i));
+ } else if ( ports[i]==VLAN_UNTAGGED ) {
+ p[2]|=(1<<(7-i));
+ p[3]&=~(1<<(7-i));
+ } else if ( ports[i]==VLAN_TAGGED ) {
+ p[2]|=(1<<(7-i));
+ p[3]|=(1<<(7-i));
}
}
- // tagged ports must be also present in untagged ports
- p[2]|=ports[3];
pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
+ ret=writeRequest(nga, attr);
+ attr=NULL;
- return writeRequest(nga, attr);
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ return ret;
+
}
+local function dissect_qos_type (buffer, offset, subtree)
+
+ local t=buffer(offset+4, 1):uint()
+ subtree:add(buffer(offset+4, 1), string.format("QoS Type: %i (%s)", t, qos_type_codes[t] or "unk"))
+
+end
+
+
+
+local function dissect_qos_config (buffer, offset, subtree)
+
+ local p=buffer(offset+5, 1):uint()
+ subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
+ subtree:add(buffer(offset+5, 1), string.format("Priority: %i (%s)", p, prio_codes[p] or "unk"))
+
+end
+
+
+
local function dissect_bitrate (buffer, offset, subtree)
local sp=buffer(offset+5, 4):uint()
end
+
local function dissect_vlan_type (buffer, offset, subtree)
local vt=buffer(offset+4, 1):uint()
end
+
local function parse_ports (val)
local ports=""
end
+
+local function dissect_vlan_port_conf (buffer, offset, subtree)
+
+ subtree:add(buffer(offset+4, 2), string.format("VLAN: %u", buffer(offset+4, 2):uint()))
+
+ if ( buffer(offset+2, 2):uint()>=3 ) then
+ subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint()))
+ end
+
+end
+
+
+
local function dissect_vlan_8021q_conf (buffer, offset, subtree)
subtree:add(buffer(offset+4, 2), string.format("VLAN: %u", buffer(offset+4, 2):uint()))
end
+
local function dissect_vlan_pvid (buffer, offset, subtree)
subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
+local function dissect_igmp_enablevlan (buffer, offset, subtree)
+
+ subtree:add(buffer(offset+4, 2), string.format("Enable: %u", buffer(offset+4, 2):uint()))
+ subtree:add(buffer(offset+6, 2), string.format("VLAN: %u", buffer(offset+6, 2):uint()))
+
+end
+
+
+
+
local attributes={
[0x0001]={name="Product", dissect="string"},
[0x0003]={name="Name", dissect="string"},
[0x000A]={name="Password", dissect="string"},
[0x000B]={name="DHCP", dissect="uint"},
[0x000D]={name="Firmware Version", dissect="string"},
+ [0x0010]={name="Firmware Upgrade", dissect="uint"},
[0x0013]={name="Restart", dissect="uint"},
[0x0400]={name="Defaults", dissect="uint"},
[0x0C00]={name="Port Status", dissect=dissect_port_status},
[0x1800]={name="Cabletest Do", dissect=nil},
[0x1C00]={name="Cabletest Result", dissect=nil},
[0x2000]={name="VLAN Type", dissect=dissect_vlan_type},
- [0x2400]={name="VLAN Port Conf", dissect=nil},
+ [0x2400]={name="VLAN Port Conf", dissect=dissect_vlan_port_conf},
[0x2800]={name="VLAN 802.1Q Conf", dissect=dissect_vlan_8021q_conf},
[0x2C00]={name="Destroy VLAN", dissect="uint"},
[0x3000]={name="VLAN PVID", dissect=dissect_vlan_pvid},
- [0x3400]={name="QoS Type", dissect=nil},
- [0x3800]={name="QoS Config", dissect=nil},
+ [0x3400]={name="QoS Type", dissect=dissect_qos_type},
+ [0x3800]={name="QoS Config", dissect=dissect_qos_config},
[0x4C00]={name="Input Bitrate", dissect=dissect_bitrate},
[0x5000]={name="Output Bitrate", dissect=dissect_bitrate},
[0x5400]={name="Broadcast Filtering State", dissect="uint"},
[0x5800]={name="Broadcast Filtering Bitrate", dissect=dissect_bitrate},
[0x5C00]={name="Mirror", dissect=dissect_mirror},
[0x6000]={name="Ports Count", dissect="uint"},
- [0x6800]={name="IGMP Enable & VLAN", dissect=nil},
+ [0x6800]={name="IGMP Enable & VLAN", dissect=dissect_igmp_enablevlan},
[0x6C00]={name="Block Unknown IGMP Addresses", dissect="uint"},
[0x7000]={name="Validate IGMPv3 Headers", dissect="uint"},
[0xFFFF]={name="End", dissect=nil}