/* * ---------------------- SYSTEM ------------------------- * * This procedure will delete/remove the given port from a switch with * ovs-vsctl del-port command. * Deleting a port from ovs switch requires only the device id, not the port * number, therefore this function needs to be called by giving the * device id as an argument in order to remove it * gchar* veth_device - the device attached to one of the ports of the switch, * e.g, uny_0 * return gboolean - TRUE if everything went fine * FALSE if something went wrong * */ gboolean deleteSwitchPort(gchar* veth_device) { //assembling the command gchar* command = g_strconcat( OVS_VSCTL_COMMAND, " del-port ", veth_device, NULL); //running the command int status = system(command); //command was successfully executed if(status == 0) { custom_log( INFO, g_strdup_printf("%s was successfully deleted from the switch", veth_device)); return TRUE; } else { custom_log(ERROR, g_strdup_printf("Error occurred during deleting %s " " from the switch", veth_device)); return FALSE; } }
/* * This helper function creates a substring of a virtual ethernet pair * containing only the first or the second device id * gchar* veth_pair_as_char - virtual ethernet pair, e.g., uny_1-uny_2 * int i - number of device (0 or 1) * return gchar* - device id */ gchar* subStringDeviceIdFromVirtualEthernetPair(gchar* veth_pair_as_char, int i) { gchar* dev = NULL; //checking whether the given veth pair is NULL if(veth_pair_as_char == NULL) { //if it is NULL custom_log(ERROR, "No virtual ethernet pair was given"); return dev; } //checking whether the desired device number is in the interval of [0,1] if(i < 0 || i > 1) { //the desired device number is out of the interval [0,1] custom_log(ERROR, "Wrong Device number, use 0 for the first one, " "and 1 for the second one"); return dev; } //for tokenizing the given veth pair gchar* tmp = g_strdup(veth_pair_as_char); //tokenize - this will produce uny_X, from uny_X-uny_Y dev = strtok(tmp,"-"); //checking which device is needed if(i == 1) { //if we need the second device, we tokenize it further //this will produce uny_Y dev = strtok(NULL,"-"); } return dev; }
void PCT_HandleMoudleMsg(PTC_ProtocolCon *pstruContoller, MSG_Buffer *pstruBuffer) { ZC_MessageHead *pstruMsg; pstruMsg = (ZC_MessageHead*)pstruBuffer->u8MsgBuffer; //u8 *u8Buf; //u8 u8Buf1[7] = {0xAA,0x83,0x01,0x01,0xaf,0x01,0x55}; /* ¿ª·äÃùÆ÷ */ //u8 u8Buf2[7] = {0xAA,0x84,0x01,0x01,0x30,0x01,0x55}; /* ¿ªµÆ */ /*start send timer*/ pstruContoller->pstruMoudleFun->pfunSetTimer(PCT_TIMER_SENDMOUDLE, PCT_TIMER_INTERVAL_SENDMOUDLE, &pstruContoller->u8SendMoudleTimer); /*copy buffer, prepare for retx*/ memcpy((u8*)g_struRetxBuffer.u8MsgBuffer, pstruBuffer->u8MsgBuffer, pstruBuffer->u32Len); g_struRetxBuffer.u32Len = pstruBuffer->u32Len; g_struRetxBuffer.u8Status = MSG_BUFFER_FULL; pstruContoller->pu8SendMoudleBuffer = (u8*)&g_struRetxBuffer; pstruContoller->u8ReSendMoudleNum = 0; /*Send to Moudle*/ pstruContoller->pstruMoudleFun->pfunSendToMoudle((u8*)pstruMsg, pstruBuffer->u32Len); /*restart heart timer*/ if (PCT_TIMER_INVAILD != pstruContoller->u8HeartTimer) { TIMER_StopTimer(pstruContoller->u8HeartTimer); } pstruContoller->pstruMoudleFun->pfunSetTimer(PCT_TIMER_SENDHEART, PCT_TIMER_INTERVAL_HEART, &pstruContoller->u8HeartTimer); #if 0 if (0x03 == pstruBuffer->u8MsgBuffer[9] && 0x01 == pstruBuffer->u8MsgBuffer[11]) { //u8Buf = u8Buf2; custom_log("open light"); UartProcess(u8Buf1, 7); } #if 0 else if (0x04 == pstruBuffer->u8MsgBuffer[9] && 0x00 == pstruBuffer->u8MsgBuffer[11]) { //u8Buf = u8Buf1; custom_log("close light"); UartProcess(u8Buf1, 7); } #endif #endif }
/* * ---------------------- DATASTRUCTURE ------------------------- * This procedure adds a string element as a value to the given string key in * the given GHashTable * GHashTable *t - the hashtable object to insert the data * gchar *key - key * gchar *value - value * gboolean supress - TRUE = supress logging, FALSE - verbose mode */ void add_string_element(GHashTable *t, gchar *key, gchar *value, gboolean supress) { if(!supress) { //verbose mode ON custom_log(INFO, g_strdup_printf("[VNF_DATASTRUCTURE] " "Adding the following key-value pair:%s - %s", key, value)); } //I do not know the reason, probably a bug, but if a key exists then the //g_hash_table_insert() does not update it, but rather cause error. //However, its documentation says that it should do this thing if(g_hash_table_contains(t,key)) { //Hashtable has already an entry with the given key custom_log(WARNING, g_strdup_printf("[VNF_DATASTRUCTURE] " "%s as key already exists!\n" "We need to remove it first!", key)); //remove the key and its corresponding data g_hash_table_remove(t, key); } //Inserting the new key-value pair int success = g_hash_table_insert(t, g_strdup (key), g_strdup(value)); if(success) { //if everything went fine if(!supress) { //verbose mode ON custom_log(INFO, g_strdup_printf("[VNF_DATASTRUCTURE] " "Key-Value pair (%s:%s) was " "successfully added!", key, value)); } } else { //if something went wrong, we do not care about verbose mode, we always //print out that an error occurred custom_log(ERROR, g_strdup_printf("[VNF_DATASTRUCTURE] " "Error during adding Key-Value pair (%s:%s)", key, value)); } }
/* * This process will start the VNF by the command that is already set to its * structure's vnf_command variable. * gchar* vnf_id - the id of the vnf * return gboolean - TRUE if everything went fine, * FALSE if something went wrong */ gboolean startVNF(gchar* vnf_id) { //getting the vnf vnf_data *found_vnf = getVNF(vnf_id); custom_log(INFO, g_strdup_printf("Starting VNF with the following command: %s", found_vnf->vnf_command)); //in order to avoid blocking main thread! //otherwise, yangcli/netconf client also waits for //termination of child process // signal(SIGCHLD, SIG_IGN); //this PID is the agent's PID, not the VNF's int processID; //checking whether forking was successful if((processID = fork()) == 0 ) { //the child process printf("-------- CHILD PROCESS"); //staring VNF int errorCode = execl("/bin/sh", "sh", "-c", found_vnf->vnf_command, (char *)NULL); //if everything went fine, we do not reach this point custom_log(ERROR, g_strdup_printf("The result of the execution is %d", errorCode)); _exit(127); } else if(processID < 0) { //error during fork custom_log(ERROR, "An error occurred during forking..."); } else { //parent process custom_log(LOG, g_strdup_printf("Command (%s) was successfully forked", found_vnf->vnf_command)); custom_log(LOG, g_strdup_printf("The VNF's PID is: %d", processID)); found_vnf->pid = processID; } return TRUE; }
/* * This procedure will disconnect the given vnf_port of the given vnf * gchar* vnf_id - the id of the vnf, e.g., vnf_1 * gchar* vnf_port - the port of the vnf, e.g., 0,1,2 */ gboolean disconnectVNF(gchar* vnf_id, gchar* vnf_port) { //getting the vnf vnf_data *found_vnf = getVNF(vnf_id); //getting the link structure vnf_link *l = g_hash_table_lookup(found_vnf->links, vnf_port); //checking whether vnf_port exists if(l == NULL) { //given vnf_port does not exist custom_log(ERROR, g_strdup_printf("%s has no link identified by %s", vnf_id, vnf_port)); return FALSE; } //disconnecting interfaces if(bringVirtualEthernetPairs(l->vnf_dev, l->sw_dev, LINK_DOWN)) { l->connected = FALSE; return TRUE; } else { return FALSE; } }
/* * ---------------------- SYSTEM ------------------------- * This helper function will practically delete the veth pairs from the system * gchar* vnf_dev - vnf's device * gchar* sw_dev - switch's device */ void deleteVirtualEthernetPair(gchar* vnf_dev, gchar* sw_dev) { //assembling the command //we do only need to delete one of the devices, since it irrevocably //deletes the other one as well gchar* command; command = g_strconcat( "ip link del ", vnf_dev, NULL); //execute the command int status = system(command); //check return value if(status == 0) { //Command was successfully executed custom_log(INFO, g_strdup_printf("Virtual ethernet pair [%s - %s] was " "successfully deleted!", vnf_dev, sw_dev)); } else if(status == 1 || status == 256) { //if device did not exist custom_log(ERROR, g_strdup_printf("Device %s not exists!",vnf_dev)); } else if(status == 2 || status == 512) { //operation not permitted custom_log(ERROR, "Operation not permitted! You must be ROOT!"); } else { //any further errors - other return values are not being examined, //just 'throw' an error custom_log(ERROR, g_strdup_printf("An error occurred during deleting " "virtual ethernet pair [%s - %s]", vnf_dev, sw_dev)); } }
/* * ---------------------- DATASTRUCTURE ------------------------- * This procedure removes a certain vnf with all its data from the hashtable * gchar *vnf_id - vnf id */ void removeVNF(gchar *vnf_id) { //removing data from the hashtable of vnfs gboolean success = g_hash_table_remove(vnfs,vnf_id); //checking whether it was successful or not if(success) { //successfully deleted custom_log(INFO, "[VNF_DATASTRUCTURE] " "VNF successfully removed!"); } else { //could not been deleted custom_log(ERROR, "[VNF_DATASTRUCTURE] " "VNF could not be removed!"); } }
/* -------------------- DATASTRUCTURE ------------------------- * This procedure adds a new link struct to a vnf datastructure * gchar* vnf_id - the id of the vnf * gchar* key - the desired key in the hash table * vnf_link* */ void addLinkToVNF(gchar* vnf_id, gchar* key, vnf_link* link) { vnf_data *found_vnf = getVNF(vnf_id); int success = g_hash_table_insert(found_vnf->links, g_strdup (key), link); if(success) { //if everything went fine custom_log(INFO, g_strdup_printf("Link is added to %s", vnf_id)); } else { //if an error occurred custom_log(ERROR, g_strdup_printf("Error during adding link to %s", vnf_id)); } }
/* * ---------------------- DATASTRUCTURE ------------------------- * Helper function to get a certain vnf as vnf_data struct * GHashTable *vnfs - hashtable of all the vnfs * gchar *vnf_id - vnf id * return vnf_data - the vnf and its data */ vnf_data* getVNF(gchar *vnf_id) { vnf_data *found_vnf; found_vnf = g_hash_table_lookup(vnfs,vnf_id); if(found_vnf == NULL) { custom_log(ERROR, g_strdup_printf("The given vnf (%s) does not exist!", vnf_id)); return NULL; } return found_vnf; }
/* * ---------------------- SYSTEM ------------------------- * This procedure connects a device to a switch, by calling ovs_vsctl add-port * command. * gchar* dev - the name of the device, e.g., uny_2 * gchar* sw_id - the id of the switch, e.g., s3 * return gchar* - switch port where the device has been attached */ gchar* connectVirtualEthernetDeviceToSwitch(gchar* dev, gchar* sw_id) { gchar* switch_port = NULL; //assembling the command gchar* command = g_strconcat(OVS_VSCTL_COMMAND, " add-port ", sw_id, " ", dev, NULL); //executing the command int status = system(command); //checking whether execution was successful if(status == 0) { //if everything went fine (return value of the command is 0) custom_log(INFO, g_strdup_printf("Device %s is connected to switch %s", dev, sw_id)); //get the newly associated port number of the connected device switch_port = getSwitchPort(sw_id,dev); } else { //something went wrong during executing the command custom_log(ERROR, g_strdup_printf("An error occurred during connecting device %s" " to switch %s", dev, sw_id)); } //we can free command, since we do not need anymore g_free(command); return switch_port; }
/* * ---------------------- DATASTRUCTURE ------------------------- * This procedure adds a vnf_data typed struct element as a value to the given * GHashTable identified by a string key. * GHashTable *t - the hashtable object to insert the data * gchar *key - key * vnf_data *data - struct to be added * * return gboolean - FALSE if something went wrong * TRUE if everything went fine */ gboolean addVNF(gchar *key, vnf_data *data) { //adding a new element int success = g_hash_table_insert(vnfs, g_strdup (key), data); if(success) { //if everything went fine custom_log(INFO, "[VNF_DATASTRUCTURE] " "VNF is added"); } else { //if an error occurred custom_log(ERROR, "[VNF_DATASTRUCTURE] " "Error during adding VNF"); } return success; }
/* * This procedure gets a certain switch port assigned to a device id * gchar* sw_id - id of the switch * gchar* dev_id - device id, which for the port is assigned * return gchar* - port number */ gchar* getSwitchPort(gchar* sw_id, gchar* dev_id) { //first we need to get all the ports and the assigned device ids with our //helper function getAllSwitchPorts(). //At the same time, we only read the corresponding port with a hashtable //lookup gchar* port = (gchar*)g_hash_table_lookup(getAllSwitchPorts(sw_id),dev_id); //check found port number if(port == NULL) { //Port number did not exists custom_log(ERROR, g_strdup_printf("%s is not connected to switch %s", dev_id, sw_id)); } return port; }
/* * This process will start the VNF by the command that is already set to its * structure's vnf_command variable. * gchar* vnf_id - the id of the vnf * return gboolean - TRUE if everything went fine, * FALSE if something went wrong */ gboolean startVNF(gchar* vnf_id) { //getting the vnf vnf_data *found_vnf = getVNF(vnf_id); //concatenating the new command by iterating through vnf's //hashtable options custom_log(INFO, "Assembling command..."); //get basic command gchar* command = g_strdup_printf("%s ", found_vnf->vnf_command); //get options GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, found_vnf->options); while(g_hash_table_iter_next(&iter, &key, &value)) { //checking whether options have no NULL values if(value == NULL) { //there is a value of NULL, we do not concatenate...continue loop continue; } //concatenate options to command command = g_strconcat(command, g_strdup_printf("%s",(gchar*)key), "=", g_strdup_printf("%s ",(gchar*)value), NULL); } //concatenate vnf_id, control_port and control_ip to command //checking whether control port is set if(found_vnf->control_port != NULL) { command = g_strconcat( command, g_strdup_printf("csPort=%s ", found_vnf->control_port), NULL); } //checking whether control_ip is set if(found_vnf->control_ip != NULL) { command = g_strconcat( command, g_strdup_printf("csIP=%s ", found_vnf->control_ip), NULL); } //concatenate vnf_id to command command = g_strconcat(command, g_strdup_printf("vnf_id=%s ", vnf_id), NULL); //concatenate links' vnf_devs //getting the keys of hashtable links GList* links_keys = g_hash_table_get_keys(found_vnf->links); GList* it = NULL; //iterating through got keys for(it = links_keys; it; it=it->next) { //concatenate keys (that are 0,1,2...) to command, //and also concatenate the corresponding vnf_dev field from //the links' structure command = g_strconcat(command, g_strdup_printf("dev_%s=", (gchar*)it->data), g_strdup_printf("%s ", ((vnf_link*)(g_hash_table_lookup(found_vnf->links, (gchar*)it->data)))->vnf_dev), NULL); } //OK, we got everything for the command...set it back to the original one found_vnf->vnf_command = g_strdup_printf("%s", command); /* * the signal() command tries to avoid blocking main thread! * * otherwise, yangcli/netconf client also waits for termination of * child process * * This signal also makes it possible to avoid <defunct> child * processes after those children was killed by system calls * * However, after this command, it doesn't wait for the * termination of its children, so stopping a chain and restarting * will fail. So, we commented the line out for the time being. */ //signal(SIGCHLD, SIG_IGN); //this PID is the agent's PID, not the VNF's int processID; //checking whether forking was successful if((processID = fork()) == 0 ) { //the child process printf("-------- CHILD PROCESS\n\n"); custom_log(INFO, g_strdup_printf("The command is: %s", found_vnf->vnf_command)); //staring VNF int errorCode = execl("/bin/sh", "sh", "-c", found_vnf->vnf_command, (char *)NULL); //if everything went fine, we do not reach this point custom_log(ERROR, g_strdup_printf("The result of the execution is %d", errorCode)); _exit(127); } else if(processID < 0) { //error during fork custom_log(ERROR, "An error occurred during forking..."); } else { //parent process custom_log(LOG, g_strdup_printf("Command (%s) was successfully forked", found_vnf->vnf_command)); custom_log(LOG, g_strdup_printf("The VNF's PID is: %d", processID)); found_vnf->pid = processID; } return TRUE; }
int mico_start_alink(void) { const uint8_t *cid; uint8_t cid_len = 0; mico_Context_t *context = mico_system_context_get(); application_config_t *app_config = context->user_config_data; int ret = -1; cid = mico_generate_cid( &cid_len ); memset(&alink_config, 0, sizeof(struct alink_config)); struct device_info* dev = (struct device_info*) malloc(sizeof(struct device_info)); memset(dev, 0, sizeof(struct device_info)); strcpy(dev->key, ALINK_KEY); strcpy(dev->secret, ALINK_SECRET); sprintf(dev->name, "%s(%c%c%c%c)",DEV_NAME, context->micoStatus.mac[12], context->micoStatus.mac[13], context->micoStatus.mac[15], context->micoStatus.mac[16]); strcpy(dev->model, DEV_MODEL); strcpy(dev->manufacturer, DEV_MANUFACTURE); strcpy(dev->type, DEV_TYPE); strcpy(dev->category, DEV_CATEGORY); strcpy(dev->sn, DEV_SN); snprintf(dev->version, STR_NAME_LEN, "%d", FIRMWARE_REVISION_NUM); memcpy(dev->mac, mico_get_mac_addr(), 18); memcpy(dev->cid, cid, Min(cid_len, STR_CID_LEN) ); custom_log("WSF", "dev->mac %s", dev->mac); custom_log("WSF", "dev->cid %s", dev->cid); #ifdef ALINK_RAWDATA custom_log("WSF", "ALINK RAWDATA !!!"); #else dev->dev_callback[ACB_GET_DEVICE_STATUS] = device_status_get; dev->dev_callback[ACB_SET_DEVICE_STATUS] = device_command_execute; #endif dev->sys_callback[ALINK_FUNC_SERVER_STATUS] = alink_network_callback; alink_set_callback(ALINK_FUNC_AVAILABLE_MEMORY, get_available_memory); #ifdef DEBUG alink_set_loglevel(ALINK_LL_NONE); #else alink_set_loglevel(ALINK_LL_NONE); #endif memset(&alink_config, 0, sizeof(struct alink_config)); #ifdef SANDBOX sandbox_setting(); #endif if( app_config->resetflag == 1) { alink_config.factory_reset = 1; } alink_set_config(&alink_config); #ifdef ALINK_RAWDATA alink_start_rawdata(dev, alink_uart_get, alink_uart_put); #else alink_start(dev); #endif alink_wait_connect(NULL,-1); free((void*)dev); return ret; }
/* * This procedure initilialize the internal hashtable * (GHashTable *vnfs) used to store vnfs */ void vnf_initializer(void) { vnfs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); custom_log(LOG, "VNF datastructure initialized"); }
/* * This procedure will gracefully stop a VNF * gchar vnf_id - the id of the vnf * return gboolean - TRUE if everythin went fine, * FALSE if something went wrong */ gboolean stopVNF(gchar* vnf_id) { log_error_bar(); //getting the vnf vnf_data *found_vnf = getVNF(vnf_id); custom_log(INFO, g_strdup_printf("[VNF DATASTRUCTURE] Deleting all data of %s", vnf_id)); //clearing some simple variables - practical freeing will handled by GLIB //set the gchar* that holds vnf command to NULL found_vnf->vnf_command = NULL; custom_log(INFO, "\tCommand is deleted"); //set the gchar* that holds vnf's control port to NULL found_vnf->control_port = NULL; custom_log(INFO, "\tControl port is deleted"); //free the gchar* that holds vnf's control IP found_vnf->control_ip = NULL; custom_log(INFO, "\tControl IP is deleted"); //removing interfaces and ports g_hash_table_foreach(found_vnf->links, (GHFunc)removeLink, NULL); //removing links g_hash_table_remove_all(found_vnf->links); //destroy hashtable g_hash_table_destroy(found_vnf->links); custom_log(INFO, "\tKilling VNF"); //assembling killing command gchar* command = g_strconcat( "pkill -TERM -P ", g_strdup_printf("%d",found_vnf->pid), NULL); custom_log(LOG, g_strdup_printf("Kill command: %s", command)); //killing process // int status = system(command); system(command); //checking whether kill was successful //DON'T KNOW WHY, BUT SYSTEM() RETURNS -1, BUT PROCESS TREE HAS BEEN //SUCCESSFULLY TERMINATED, THEREFORE THE FOLLOWING PART IS COMMENTED // if(status == 0) // { // custom_log(INFO, g_strdup_printf("VNF (pid: %d) was successfully killed!", // found_vnf->pid)); // // } // else // { // // custom_log(ERROR, g_strdup_printf("Error occurred during killing VNF (pid: %d)", // found_vnf->pid)); // // //checking whether pid is real // if(status == 1 || status == 256) // { // //Process ID not found // custom_log(ERROR, g_strdup_printf("There is no PID like %d",found_vnf->pid)); // } // // //print return value // custom_log(ERROR, g_strdup_printf("Return value of pkill: %d", status)); // // return FALSE; // } //set the gchar* that holds vnf's PID to NULL found_vnf->pid = -1; //removing vnf datastructure from the main vnf hashtable removeVNF(vnf_id); return TRUE; }
/* * This procedure will connect the given vnf to the given switch via the given/ * requested vnf_port * gchar* vnf_id - the id of the vnf * gchar* vnf_port - one of the vnf's available ports * gchar* switch_id - the id of the switch * return gchar* - the port number of the switch */ gchar* connectVNF(gchar* vnf_id, gchar* vnf_port, gchar* switch_id) { //getting the vnf vnf_data *found_vnf = getVNF(vnf_id); //for the link structure vnf_link *l = NULL; //this is the return value. The switch port will be determined by an //ovs-vsctl command gchar* sw_port = NULL; //checking whether a link is existed if(g_hash_table_lookup_extended(found_vnf->links, vnf_port, NULL, NULL) == FALSE) { //create new link and connecting l = initLink(); gchar* uny_pair = createVirtualEthernetPairs(); gchar* vnf_dev = subStringDeviceIdFromVirtualEthernetPair(uny_pair,0); gchar* sw_dev = subStringDeviceIdFromVirtualEthernetPair(uny_pair,1); sw_port = connectVirtualEthernetDeviceToSwitch(sw_dev,switch_id); //setting link params l->vnf_dev = vnf_dev; l->sw_dev = sw_dev; l->sw_id = switch_id; l->sw_port = sw_port; //bringing up virtual ethernet pairs if(bringVirtualEthernetPairs(vnf_dev, sw_dev, LINK_UP)) { //bringing up was successful l->connected = TRUE; custom_log(INFO, g_strdup_printf("%s (%s) is connected to switch %s" " (%s)", vnf_id, vnf_dev, switch_id, sw_dev)); } else { //something went wrong during bringing up interfaces l->connected = FALSE; } //adding link to vnf's datastructure addLinkToVNF(vnf_id, vnf_port, l); } else { //the given link already existed //getting the link structure l = g_hash_table_lookup(found_vnf->links, vnf_port); //checking whether the switch_id assigned to the link is equal to //the given switch_id if(g_strcmp0(l->sw_id, switch_id) == 0) { //RECONNECT if(bringVirtualEthernetPairs(l->vnf_dev, l->sw_dev, LINK_UP)) { //bringing up was successful l->connected = TRUE; custom_log(INFO, g_strdup_printf("%s (%s) is reconnected to " "switch %s (%s)", vnf_id, l->vnf_dev, switch_id, l->sw_dev)); } else { //something went wrong during bringing up interfaces l->connected = FALSE; } sw_port = l->sw_port; } else { //TODO: if a connection entry is already existed for the given // vnf_port, but the assigned switch_id is different than // the given switch_id sw_port = NULL; custom_log(ERROR, "WRONG arguments have been set for connect func"); } } return sw_port; }
/* * ---------------------- SYSTEM ------------------------- * This procedure will actually bring up the virtual ethernet pairs, since * even if both ends of it are connected to some switches, they are in DOWN * state. * gchar* vnf_dev - the virtual ethernet device assigned to the vnf * gchar* sw_dev - the virtual ethernet device assigned to the switch * gint status - LINK_UP or LINK_DOWN * up * return gboolean - TRUE if everything went fine * FALSE if something went wrong */ gboolean bringVirtualEthernetPairs(gchar* vnf_dev, gchar* sw_dev, gint status) { //setting up the status gchar* st = ""; if(status == LINK_DOWN) { st = " down "; } else if(status == LINK_UP) { st = " up "; } else { //status information was not correctly set return FALSE; } //assembling the first bring-up command gchar* command_1 = g_strconcat("ip link set ", vnf_dev, st, NULL); //executing the first bring-up command int returnValue = system(command_1); // custom_log(LOG, g_strdup_printf("Return value: %d", returnValue)); //checking whether execution was successful if(returnValue == 0) { //if everything went fine (return value of the command is 0) custom_log(INFO, g_strdup_printf("Device %s has been brought %s", vnf_dev, st)); } else { //something went wrong during executing the command custom_log(ERROR, g_strdup_printf("An error occurred during bringing %s" " device %s", st, vnf_dev)); return FALSE; } //we can free command_1, since we do not need anymore g_free(command_1); //assembling the second command gchar* command_2 = g_strconcat("ip link set ", sw_dev, st, NULL); //executing the first bring-up command returnValue = system(command_2); //checking whether execution was successful if(returnValue == 0) { //if everything went fine (return value of the command is 0) custom_log(INFO, g_strdup_printf("Device %s has been brought %s", sw_dev, st)); } else { //something went wrong during executing the command custom_log(ERROR, g_strdup_printf("An error occurred during bringing %s" " device %s", st, sw_dev)); return FALSE; } //we can free command_1, since we do not need anymore g_free(command_2); return TRUE; }
/* * ---------------------- SYSTEM ------------------------- * This procedure will create a practical veth pairs by system calls. * It also checks other existing veth pairs, and automatically determine, which * name should be assigned to the new veth pairs. * return gchar* - veth_pair_as_char consisting of the newly created veth pairs * in order to set it for a vnf by addVirtualEthernetPairs(...) function */ gchar* createVirtualEthernetPairs(void) { //for storing all the uny_X devices' numbers (X) GSList *device_numbers = NULL; //a line for stdout char path[100]; //found device, e.g., uny_3 gchar *dev; //for running a command and read its stdout FILE *get_veths; //first we need to get actual uny_X devices get_veths = popen("ip link | grep uny| cut -d ' ' -f 2", "r"); //the result is like: 'uny_2:' //checking that command was run successfully if(get_veths == NULL) { custom_log(ERROR, "Failed to run command"); } //command execution succeeded else { //reading stdout while(fgets(path,sizeof(path)-1, get_veths) != NULL) { //this will produce 'uny' from 'uny_X:' dev = strtok(path,"_"); //this will produce the number (id) after 'uny_' without the colon dev = strtok(NULL,":"); // g_print(dev); //we store them as gchars, since they can be easier handled in a //GSList* //adding found device numbers (ids) to a list device_numbers = g_slist_append( device_numbers, g_strdup(dev) ); } } //close FILE pclose(get_veths); //getting the highest device number gint highestDevID = atoi(getHighestDeviceID(device_numbers)); //the new device id needs to be increased with one highestDevID++; //this will be the first new id (Y > max(X)) gchar *newDevID_1 = g_strdup_printf("%d",highestDevID); //the second device id also needs to be increased with one highestDevID++; //this will be the second new id for the new peer dev (Y' > Y) gchar *newDevID_2 = g_strdup_printf("%d",highestDevID); //assembling command //ip link add uny_Y type veth peer name uny_Y' gchar *command = g_strconcat( "ip link add uny_", newDevID_1, " type veth peer name uny_", newDevID_2, NULL); //for executing the command // custom_log(INFO, g_strdup_printf("command:%s\n\n", command)); int status = system(command); //command was successfully executed if(status == 0) { //if everything went fine (return value of the command is 0) custom_log(INFO, g_strdup_printf("A new veth pair has been created: " "(uny_%s - uny_%s)", newDevID_1, newDevID_2)); //we can free up gchar* command, since we do not require it anymore g_free(command); //concatenating the return value, e.g., uny_1-uny_2 gchar* veth_pair_as_char = g_strconcat("uny_", newDevID_1, "-uny_", newDevID_2, NULL); return veth_pair_as_char; } else if(status == 2 || status == 512) { //return value of the command is 2 or 512 -> operation not permitted custom_log(ERROR, "Operation not permitted! You must be ROOT!"); return NULL; } else { //other return values are not being examined, just 'throw' an error custom_log(ERROR, "An error occurred during creating veth pairs!\n" "Operation may not permitted - You must be ROOT!"); return NULL; } }
/* * ---------------------- SYSTEM ------------------------- * This function collects the ports and corresponding device ids of the given * switch * gchar* sw_id - id of the switch, e.g., s3 * return GHashTable* - hashtable of the results ([port_num]=dev_id) */ GHashTable* getAllSwitchPorts(gchar* sw_id) { //for storing all the device ids and the corresponding ports GHashTable *switch_ports_and_dev_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); //a line for stdout char path[100]; //found ports and devices, e.g., 2(s3-eth2) gchar *ports_and_devices; //for running a command and reading its stdout FILE *get_ports_and_devices; //assembling the command //the corresponding line always consists of a mac address info, for instance //addr:46:be....., so we can grep 'addr' on the stdout. //The results will look like the following: //2(s3-eth2): addr:5a:42:6f:11:25:81 //We can further use system calls for easing handling such as 'cut' gchar* command = g_strconcat( OVS_OFCTL_COMMAND, " show ", sw_id, "| grep addr|cut -d ':' -f 1", NULL); //run the command get_ports_and_devices = popen(command, "r"); //This result, which must be parsed will look like this: 2(uny_X) //checking that command was run successfully if(get_ports_and_devices == NULL) { //error occurred during executing command custom_log(ERROR, g_strdup_printf("Failed to run command (%s)",command)); } else { //command execution succeeded //reading stdout while(fgets(path,sizeof(path)-1, get_ports_and_devices) != NULL) { gchar* port; gchar* device_id; //tokenizing read line //this will produce '2' from '2(uny_X)' //this will produce 2 ports_and_devices = strtok(path,"("); //duplicating variable port = g_strdup(ports_and_devices); //tokenize further //this will produce uny_X ports_and_devices = strtok(NULL,")"); //storing uny_X in device_id device_id = g_strdup(ports_and_devices); //we need to remove the first whitespace character from port, so //here comes a trick with the tokenizer port = strtok(port," "); // g_print("port:%s\n", port); // g_print("dev_id:%s\n\n",device_id); //adding port and device ids to the hashtable add_string_element(switch_ports_and_dev_ids, g_strdup(device_id), g_strdup(port), TRUE); } } //close FILE pclose(get_ports_and_devices); //freeing gchar* command, since we do not need it anymore g_free(command); return switch_ports_and_dev_ids; }