📄 eth_switch.c
字号:
t->nio[i] = nio; netio_rxl_add(nio,(netio_rx_handler_t)ethsw_recv_pkt,t,NULL); ETHSW_UNLOCK(t); return(0); error: ETHSW_UNLOCK(t); return(-1);}/* Free resources used by a NIO */static void ethsw_free_nio(netio_desc_t *nio){ netio_rxl_remove(nio); netio_release(nio->name);}/* Remove a NetIO descriptor from a virtual ethernet switch */int ethsw_remove_netio(ethsw_table_t *t,char *nio_name){ netio_desc_t *nio; int i; ETHSW_LOCK(t); if (!(nio = registry_exists(nio_name,OBJ_TYPE_NIO))) goto error; /* Try to find the NIO in the NIO array */ for(i=0;i<ETHSW_MAX_NIO;i++) if (t->nio[i] == nio) break; if (i == ETHSW_MAX_NIO) goto error; /* Invalidate this port in the MAC address table */ ethsw_invalidate_port(t,nio); t->nio[i] = NULL; ETHSW_UNLOCK(t); /* Remove the NIO from the RX multiplexer */ ethsw_free_nio(nio); return(0); error: ETHSW_UNLOCK(t); return(-1);}/* Clear the MAC address table */int ethsw_clear_mac_addr_table(ethsw_table_t *t){ ETHSW_LOCK(t); ethsw_invalidate(t); ETHSW_UNLOCK(t); return(0);}/* Iterate over all entries of the MAC address table */int ethsw_iterate_mac_addr_table(ethsw_table_t *t,ethsw_foreach_entry_t cb, void *opt_arg){ ethsw_mac_entry_t *entry; int i; ETHSW_LOCK(t); for(i=0;i<ETHSW_HASH_SIZE;i++) { entry = &t->mac_addr_table[i]; if (!entry->nio) continue; cb(t,entry,opt_arg); } ETHSW_UNLOCK(t); return(0);}/* Set port as an access port */int ethsw_set_access_port(ethsw_table_t *t,char *nio_name,u_int vlan_id){ int i,res = -1; ETHSW_LOCK(t); for(i=0;i<ETHSW_MAX_NIO;i++) if (t->nio[i] && !strcmp(t->nio[i]->name,nio_name)) { set_access_port(t->nio[i],vlan_id); res = 0; break; } ETHSW_UNLOCK(t); return(res);}/* Set port as a 802.1q trunk port */int ethsw_set_dot1q_port(ethsw_table_t *t,char *nio_name,u_int native_vlan){ int i,res = -1; ETHSW_LOCK(t); for(i=0;i<ETHSW_MAX_NIO;i++) if (t->nio[i] && !strcmp(t->nio[i]->name,nio_name)) { set_dot1q_port(t->nio[i],native_vlan); res = 0; break; } ETHSW_UNLOCK(t); return(res);}/* Save the configuration of a switch */void ethsw_save_config(ethsw_table_t *t,FILE *fd){ netio_desc_t *nio; int i; fprintf(fd,"ethsw create %s\n",t->name); ETHSW_LOCK(t); for(i=0;i<ETHSW_MAX_NIO;i++) { nio = t->nio[i]; fprintf(fd,"ethsw add_nio %s %s\n",t->name,nio->name); switch(nio->vlan_port_type) { case ETHSW_PORT_TYPE_ACCESS: fprintf(fd,"ethsw set_access_port %s %s %u\n", t->name,nio->name,nio->vlan_id); break; case ETHSW_PORT_TYPE_DOT1Q: fprintf(fd,"ethsw set_dot1q_port %s %s %u\n", t->name,nio->name,nio->vlan_id); break; default: fprintf(stderr,"ethsw_save_config: unknown port type %u\n", nio->vlan_port_type); } } ETHSW_UNLOCK(t); fprintf(fd,"\n");}/* Save configurations of all Ethernet switches */static void ethsw_reg_save_config(registry_entry_t *entry,void *opt,int *err){ ethsw_save_config((ethsw_table_t *)entry->data,(FILE *)opt);}void ethsw_save_config_all(FILE *fd){ registry_foreach_type(OBJ_TYPE_ETHSW,ethsw_reg_save_config,fd,NULL);}/* Free resources used by a virtual ethernet switch */static int ethsw_free(void *data,void *arg){ ethsw_table_t *t = data; int i; for(i=0;i<ETHSW_MAX_NIO;i++) { if (!t->nio[i]) continue; ethsw_free_nio(t->nio[i]); } free(t->name); free(t); return(TRUE);}/* Delete a virtual ethernet switch */int ethsw_delete(char *name){ return(registry_delete_if_unused(name,OBJ_TYPE_ETHSW,ethsw_free,NULL));}/* Delete all virtual ethernet switches */int ethsw_delete_all(void){ return(registry_delete_type(OBJ_TYPE_ETHSW,ethsw_free,NULL));}/* Create a new interface */static int ethsw_cfg_create_if(ethsw_table_t *t,char **tokens,int count){ netio_desc_t *nio = NULL; int nio_type; nio_type = netio_get_type(tokens[2]); switch(nio_type) { case NETIO_TYPE_UNIX: if (count != 5) { fprintf(stderr,"ETHSW: invalid number of arguments " "for UNIX NIO\n"); break; } nio = netio_desc_create_unix(tokens[1],tokens[3],tokens[4]); break; case NETIO_TYPE_TAP: if (count != 4) { fprintf(stderr,"ETHSW: invalid number of arguments " "for TAP NIO\n"); break; } nio = netio_desc_create_tap(tokens[1],tokens[3]); break; case NETIO_TYPE_UDP: if (count != 6) { fprintf(stderr,"ETHSW: invalid number of arguments " "for UDP NIO\n"); break; } nio = netio_desc_create_udp(tokens[1],atoi(tokens[3]), tokens[4],atoi(tokens[5])); break; case NETIO_TYPE_TCP_CLI: if (count != 5) { fprintf(stderr,"ETHSW: invalid number of arguments " "for TCP CLI NIO\n"); break; } nio = netio_desc_create_tcp_cli(tokens[1],tokens[3],tokens[4]); break; case NETIO_TYPE_TCP_SER: if (count != 4) { fprintf(stderr,"ETHSW: invalid number of arguments " "for TCP SER NIO\n"); break; } nio = netio_desc_create_tcp_ser(tokens[1],tokens[3]); break;#ifdef GEN_ETH case NETIO_TYPE_GEN_ETH: if (count != 4) { fprintf(stderr,"ETHSW: invalid number of arguments " "for Generic Ethernet NIO\n"); break; } nio = netio_desc_create_geneth(tokens[1],tokens[3]); break;#endif#ifdef LINUX_ETH case NETIO_TYPE_LINUX_ETH: if (count != 4) { fprintf(stderr,"ETHSW: invalid number of arguments " "for Linux Ethernet NIO\n"); break; } nio = netio_desc_create_lnxeth(tokens[1],tokens[3]); break;#endif default: fprintf(stderr,"ETHSW: unknown/invalid NETIO type '%s'\n", tokens[2]); } if (!nio) { fprintf(stderr,"ETHSW: unable to create NETIO descriptor\n"); return(-1); } if (ethsw_add_netio(t,tokens[1]) == -1) { fprintf(stderr,"ETHSW: unable to add NETIO descriptor.\n"); netio_release(nio->name); return(-1); } netio_release(nio->name); return(0);}/* Set a port as an access port */static int ethsw_cfg_set_access_port(ethsw_table_t *t,char **tokens,int count){ /* 3 parameters: "ACCESS", IF, VLAN */ if (count != 3) { fprintf(stderr,"ETHSW: invalid access port description.\n"); return(-1); } return(ethsw_set_access_port(t,tokens[1],atoi(tokens[2])));}/* Set a port as a 802.1q trunk port */static int ethsw_cfg_set_dot1q_port(ethsw_table_t *t,char **tokens,int count){ /* 3 parameters: "DOT1Q", IF, Native VLAN */ if (count != 3) { fprintf(stderr,"ETHSW: invalid trunk port description.\n"); return(-1); } return(ethsw_set_dot1q_port(t,tokens[1],atoi(tokens[2])));}#define ETHSW_MAX_TOKENS 16/* Handle a ETHSW configuration line */static int ethsw_handle_cfg_line(ethsw_table_t *t,char *str){ char *tokens[ETHSW_MAX_TOKENS]; int count; if ((count = m_strsplit(str,':',tokens,ETHSW_MAX_TOKENS)) <= 1) return(-1); if (!strcmp(tokens[0],"IF")) return(ethsw_cfg_create_if(t,tokens,count)); else if (!strcmp(tokens[0],"ACCESS")) return(ethsw_cfg_set_access_port(t,tokens,count)); else if (!strcmp(tokens[0],"DOT1Q")) return(ethsw_cfg_set_dot1q_port(t,tokens,count)); fprintf(stderr, "ETHSW: Unknown statement \"%s\" (allowed: IF,ACCESS,TRUNK)\n", tokens[0]); return(-1);}/* Read a ETHSW configuration file */static int ethsw_read_cfg_file(ethsw_table_t *t,char *filename){ char buffer[1024],*ptr; FILE *fd; if (!(fd = fopen(filename,"r"))) { perror("fopen"); return(-1); } while(!feof(fd)) { if (!fgets(buffer,sizeof(buffer),fd)) break; /* skip comments and end of line */ if ((ptr = strpbrk(buffer,"#\r\n")) != NULL) *ptr = 0; /* analyze non-empty lines */ if (strchr(buffer,':')) ethsw_handle_cfg_line(t,buffer); } fclose(fd); return(0);}/* Start a virtual Ethernet switch */int ethsw_start(char *filename){ ethsw_table_t *t; if (!(t = ethsw_create("default"))) { fprintf(stderr,"ETHSW: unable to create virtual fabric table.\n"); return(-1); } if (ethsw_read_cfg_file(t,filename) == -1) { fprintf(stderr,"ETHSW: unable to parse configuration file.\n"); return(-1); } ethsw_release("default"); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -