/*********************************************************************** * The task function of the datapath task * Form: static void pofdp_main_task(void *arg_ptr) * Input: NONE * Output: NONE * Return: VOID * Discribe: This is the main function of the datapath task, which is * infinite loop running. It receive the RAW packet, and forward. * The next RAW packet will be not proceeded until the forward * process of the last packet is over. * NOTE: The datapath task will be terminated if some ERROR occurs * during the receive process and the datapath process. ***********************************************************************/ static uint32_t pofdp_main_task(void *arg_ptr){ uint8_t recv_buf[POFDP_PACKET_RAW_MAX_LEN] = {0}; struct pofdp_packet dpp[1] = {0}; struct pof_instruction first_ins[1] = {0}; uint32_t len_B = 0, port_id = 0; uint32_t ret; /* Set GOTO_TABLE instruction to go to the first flow table. */ set_goto_first_table_instruction(first_ins); while(1){ /* Receive raw packet through local physical OpenFlow-enabled ports. */ ret = pofdp_recv_raw(dpp); if(ret != POF_OK){ POF_CHECK_RETVALUE_NO_RETURN_NO_UPWARD(ret); /* Delay 0.1s to send error message upward to the Controller. */ pofbf_task_delay(100); terminate_handler(); } /* Check the packet length. */ if(dpp->ori_len > POFDP_PACKET_RAW_MAX_LEN){ free_packet_data(dpp); POF_ERROR_HANDLE_NO_RETURN_NO_UPWARD(POFET_SOFTWARE_FAILED, POF_PACKET_LEN_ERROR); continue; } /* Check whether the first flow table exist. */ if(POF_OK != poflr_check_flow_table_exist(POFDP_FIRST_TABLE_ID)){ POF_DEBUG_CPRINT_FL(1,RED,"Received a packet, but the first flow table does NOT exist."); free_packet_data(dpp); continue; } /* Forward the packet. */ ret = pofdp_forward(dpp, first_ins); POF_CHECK_RETVALUE_NO_RETURN_NO_UPWARD(ret); free_packet_data(dpp); POF_DEBUG_CPRINT_FL(1,GREEN,"one packet_raw has been processed!\n"); } return POF_OK; }
void free_packet(struct packet *p) { assert(p != NULL); assert(p->pdata != NULL); assert_packet_type(p->header.type); assert_valid_pdata(p); assert_valid_ndata(p); if (p->pdata && p->pdata_len > 0) { free_packet_data(p); free(p->pdata); p->pdata_len = 0; } if (p->ndata && p->ndata_len > 0) { free(p->ndata); p->ndata_len = 0; } }
/*********************************************************************** * The task function of receive task * Form: static void pofdp_recv_raw_task(void *arg_ptr) * Input: port infomation * Output: NONE * Return: VOID * Discribe: This is the task function of receive task, which is infinite * loop running. It receives RAW packet by binding socket to the * local physical net port spicified in the port infomation. * After filtering, the packet data and port infomation will be * assembled with format of struct pofdp_packet, and be send * into the receive queue. The only parameter arg_ptr is the * pointer of the local physical net port infomation which has * been assembled with format of struct pof_port. * NOTE: This task will be terminated if any ERRORs occur. * If the openflow function of this physical port is disable, * it will be still loop running but nothing will be received. ***********************************************************************/ static uint32_t pofdp_recv_raw_task(void *arg_ptr){ pof_port *port_ptr = (pof_port *)arg_ptr; struct pofdp_packet *dpp = malloc(sizeof *dpp); struct sockaddr_ll sockadr, from; uint32_t from_len, len_B; uint8_t buf[POFDP_PACKET_RAW_MAX_LEN]; int sock; from_len = sizeof(struct sockaddr_ll); /* Create socket, and bind it to the specific port. */ if((sock = socket(AF_PACKET, SOCK_RAW, POF_HTONS(ETH_P_ALL))) == -1){ POF_ERROR_HANDLE_NO_RETURN_UPWARD(POFET_SOFTWARE_FAILED, POF_CREATE_SOCKET_FAILURE, g_upward_xid++); /* Delay 0.1s to send error message upward to the Controller. */ pofbf_task_delay(100); terminate_handler(); } sockadr.sll_family = AF_PACKET; sockadr.sll_protocol = POF_HTONS(ETH_P_ALL); sockadr.sll_ifindex = port_ptr->port_id; if(bind(sock, (struct sockaddr *)&sockadr, sizeof(struct sockaddr_ll)) != 0){ POF_ERROR_HANDLE_NO_RETURN_UPWARD(POFET_SOFTWARE_FAILED, POF_BIND_SOCKET_FAILURE, g_upward_xid++); /* Delay 0.1s to send error message upward to the Controller. */ pofbf_task_delay(100); terminate_handler(); } /* Receive the raw packet through the specific port. */ while(1){ pthread_testcancel(); /* Receive the raw packet. */ if((len_B = recvfrom(sock, buf, POFDP_PACKET_RAW_MAX_LEN, 0, (struct sockaddr *)&from, &from_len)) <=0){ POF_ERROR_HANDLE_NO_RETURN_UPWARD(POFET_SOFTWARE_FAILED, POF_RECEIVE_MSG_FAILURE, g_upward_xid++); continue; } /* Check whether the OpenFlow-enabled of the port is on or not. */ if(port_ptr->of_enable == POFLR_PORT_DISABLE){ continue; } /* Check the packet length. */ if(len_B > POF_MTU_LENGTH){ POF_DEBUG_CPRINT_FL(1,RED,"The packet received is longer than MTU. DROP!"); continue; } /* Filter the received raw packet by some rules. */ if(pofdp_packet_raw_filter(buf, port_ptr) != POF_OK){ continue; } /* Store packet data, length, received port infomation into the message queue. */ memset(dpp, 0, sizeof *dpp); dpp->ori_port_id = port_ptr->port_id; malloc_packet_data(dpp, len_B); memcpy(dpp->buf, buf, len_B); if(pofbf_queue_write(g_pofdp_recv_q_id, dpp, sizeof *dpp, POF_WAIT_FOREVER) != POF_OK){ POF_ERROR_HANDLE_NO_RETURN_UPWARD(POFET_SOFTWARE_FAILED, POF_WRITE_MSG_QUEUE_FAILURE, g_upward_xid++); free_packet_data(dpp); pofbf_task_delay(100); terminate_handler(); } } close(sock); return POF_OK; }