/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ /*************************************************************************** rb_tool.c - User-space utility for driving NASMESH IOCTL interface ------------------- copyright : (C) 2008 by Eurecom email : raymond.knopp@eurecom.fr and navid.nikaein@eurecom.fr *************************************************************************** ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include //#include "rrc_nas_primitives.h" #include "ioctl.h" #include "constant.h" #define NIPADDR(addr) \ (uint8_t)(addr & 0x000000FF), \ (uint8_t)((addr & 0x0000FF00) >> 8), \ (uint8_t)((addr & 0x00FF0000) >> 16), \ (uint8_t)((addr & 0xFF000000) >> 24) #define NIP6ADDR(addr) \ ntohs((addr)->s6_addr16[0]), \ ntohs((addr)->s6_addr16[1]), \ ntohs((addr)->s6_addr16[2]), \ ntohs((addr)->s6_addr16[3]), \ ntohs((addr)->s6_addr16[4]), \ ntohs((addr)->s6_addr16[5]), \ ntohs((addr)->s6_addr16[6]), \ ntohs((addr)->s6_addr16[7]) // Global variables int fd; //ioctl char dummy_buffer[1024]; struct oai_nw_drv_ioctl gifr; //int wait_start_nas; //--------------------------------------------------------------------------- void IAL_NAS_ioctl_init(int inst) //--------------------------------------------------------------------------- { struct oai_nw_drv_msg_statistic_reply *msgrep; int err,rc; sprintf(gifr.name, "oai%d",inst); // Get an UDP IPv6 socket ?? fd=socket(AF_INET6, SOCK_DGRAM, 0); if (fd<0) { printf("Error opening socket\n"); exit(1); } sprintf(gifr.name, "oai%d",inst); gifr.type = OAI_NW_DRV_MSG_STATISTIC_REQUEST; memset ((void *)dummy_buffer,0,800); gifr.msg= &(dummy_buffer[0]); msgrep=(struct oai_nw_drv_msg_statistic_reply *)(gifr.msg); printf("ioctl :Statistics requested\n"); err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); if (err<0) { printf("IOCTL error, err=%d\n",err); rc = -1; } printf("tx_packets = %u, rx_packets = %u\n", msgrep->tx_packets, msgrep->rx_packets); printf("tx_bytes = %u, rx_bytes = %u\n", msgrep->tx_bytes, msgrep->rx_bytes); printf("tx_errors = %u, rx_errors = %u\n", msgrep->tx_errors, msgrep->rx_errors); printf("tx_dropped = %u, rx_dropped = %u\n", msgrep->tx_dropped, msgrep->rx_dropped); } #define NO_ACTION_RB 0 #define ADD_RB 1 #define DEL_RB 2 //--------------------------------------------------------------------------- int main(int argc,char **argv) //--------------------------------------------------------------------------- { int done; int rc; int meas_polling_counter; fd_set readfds; struct timeval tv; int i; int err; char *buffer; int c; int action; int rbset = 0; int cxset = 0; int classrefset = 0; int instset = 0; int saddr_ipv4set = 0; int saddr_ipv6set = 0; int daddr_ipv4set = 0; int daddr_ipv6set = 0; int dscpset = 0; int dplen = 0; int splen = 0; int mpls_outlabelset = 0; int mpls_inlabelset; char rb[20]; char cx[20]; char classref[20]; char dscp[20]; char inst[20]; char mpls_outgoinglabel[100]; char mpls_incominglabel[100]; int index; struct oai_nw_drv_msg_rb_establishment_request *msgreq; struct oai_nw_drv_msg_class_add_request *msgreq_class; in_addr_t saddr_ipv4; in_addr_t daddr_ipv4; struct in6_addr saddr_ipv6; struct in6_addr daddr_ipv6; unsigned int mpls_outlabel; unsigned int mpls_inlabel; char addr_str[46]; char mask_len_delims[] = "/"; char *result; // scan options rb[0] = '\0'; cx[0] = '\0'; dscp[0] = '\0'; mpls_incominglabel[0] = '\0'; mpls_outgoinglabel[0] = '\0'; action = NO_ACTION_RB; while ((c = getopt (argc, argv, "adr:i:c:f:l:m:s:t:x:y:z:")) != -1) switch (c) { case 'a': action = ADD_RB; break; case 'd': action = DEL_RB; break; case 'r': strcpy(rb,optarg); rbset = 1; break; case 'i': strcpy(inst,optarg); instset = 1; break; case 'c': strcpy(cx,optarg); cxset = 1; break; case 'f': strcpy(classref,optarg); classrefset = 1; break; case 'l': strcpy(mpls_outgoinglabel,optarg); mpls_outlabelset=1; break; case 'm': strcpy(mpls_incominglabel,optarg); mpls_inlabelset=1; break; case 's': result = strtok( optarg, mask_len_delims ); if ( result != NULL ) { inet_aton(result,&saddr_ipv4); printf("Arg Source Addr IPv4 string: %s\n",result); saddr_ipv4set = 1; } else { printf("Arg Source Addr IPv4 string: ERROR\n"); break; } result = strtok( NULL, mask_len_delims ); if ( result != NULL ) { splen = atoi(result); } else { splen = 32; } printf("Arg Source Addr IPv4 mask len: %d\n",splen); break; case 't': result = strtok( optarg, mask_len_delims ); if ( result != NULL ) { inet_aton(result,&daddr_ipv4); printf("Arg Dest Addr IPv4 string: %s\n",result); daddr_ipv4set = 1; } else { printf("Arg Dest Addr IPv4 string: ERROR\n"); break; } result = strtok( NULL, mask_len_delims ); if ( result != NULL ) { dplen = atoi(result); } else { dplen = 32; } printf("Arg Dest Addr IPv4 mask len: %d\n",dplen); break; case 'x': result = strtok( optarg, mask_len_delims ); if ( result != NULL ) { printf("Arg Source Addr IPv6 string: %s\n",result); inet_pton(AF_INET6,result,(void *)&saddr_ipv6); saddr_ipv6set = 1; } else { printf("Arg Source Addr IPv6 string: ERROR\n"); break; } result = strtok( NULL, mask_len_delims ); if ( result != NULL ) { splen = atoi(result); } else { splen = 128; } printf("Arg Source Addr IPv6 mask len: %d\n",splen); break; case 'y': result = strtok( optarg, mask_len_delims ); if ( result != NULL ) { printf("Arg Dest Addr IPv6 string: %s\n",result); inet_pton(AF_INET6,result,(void *)&daddr_ipv6); daddr_ipv6set = 1; } else { printf("Arg Dest Addr IPv6 string: ERROR\n"); break; } result = strtok( NULL, mask_len_delims ); if ( result != NULL ) { dplen = atoi(result); } else { dplen = 128; } printf("Arg Dest Addr IPv6 mask len: %d\n",dplen); break; case 'z': dscpset=1; strcpy(dscp,optarg); break; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: abort (); } printf ("action = %d, rb = %s,cx = %s\n", action, rb, cx); if (rbset==0) { printf("ERROR: Specify a RAB id!!\n"); exit(-1); } if (cxset==0) { printf("ERROR: Specify an LCR !!\n"); exit(-1); } if (classrefset==0) { printf("ERROR: Specify an Class reference !!\n"); exit(-1); } if (instset==0) { printf("ERROR: Specify an interface !!\n"); exit(-1); } if ((mpls_outlabelset == 0) && (saddr_ipv4set==0) && (saddr_ipv6set==0)) { printf("ERROR: Specify a source IP address\n"); exit(-1); } if ((mpls_outlabelset == 0) && (daddr_ipv4set==0) && (daddr_ipv6set==0)) { printf("ERROR: Specify a destination IP address\n"); exit(-1); } if ((mpls_outlabelset == 1) && (mpls_inlabelset == 0)) { printf("ERROR: Specify an incoming MPLS label\n"); exit(-1); } if ((mpls_inlabelset == 1) && (mpls_outlabelset == 0)) { printf("ERROR: Specify an outgoing MPLS label\n"); exit(-1); } IAL_NAS_ioctl_init(atoi(inst)); msgreq = (struct oai_nw_drv_msg_rb_establishment_request *)(gifr.msg); msgreq->rab_id = atoi(rb); msgreq->lcr = atoi(cx); msgreq->qos = 0; if (action == ADD_RB) { gifr.type = OAI_NW_DRV_MSG_RB_ESTABLISHMENT_REQUEST; printf("OAI_NW_DRV_MSG_RB_ESTABLISHMENT_REQUEST: RB %d LCR %d QOS %d\n ", msgreq->rab_id, msgreq->lcr, msgreq->qos); err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); } // only add classification rule if ((action == ADD_RB ) || (action == NO_ACTION_RB)) { if (saddr_ipv4set == 1) { msgreq_class = (struct oai_nw_drv_msg_class_add_request *)(gifr.msg); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->version = 4; msgreq_class->classref = atoi(classref) + (msgreq_class->lcr<<8); msgreq_class->dir = OAI_NW_DRV_DIRECTION_SEND; msgreq_class->fct = OAI_NW_DRV_FCT_QOS_SEND; msgreq_class->saddr.ipv4 = saddr_ipv4; msgreq_class->daddr.ipv4 = daddr_ipv4; msgreq_class->dplen = dplen; msgreq_class->splen = splen; // TO BE FIXED WHEN WE CAN SPECIFY A PROTOCOL-based rule msgreq_class->protocol = OAI_NW_DRV_PROTOCOL_DEFAULT; if (dscpset==0) { msgreq_class->dscp=0; } else { msgreq_class->dscp=atoi(dscp); } printf("OAI_NW_DRV_MSG_CLASS_ADD_REQUEST: OAI_NW_DRV_DIRECTION_SEND RB %d LCR %d ClassRef %d ", msgreq_class->rab_id, msgreq_class->lcr, msgreq_class->classref); printf("IPV4: Source = %d.%d.%d.%d/%d ", NIPADDR(msgreq_class->saddr.ipv4), msgreq_class->splen); printf(" IPV4: Dest = %d.%d.%d.%d/%d\n", NIPADDR(msgreq_class->daddr.ipv4), msgreq_class->dplen); gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->version = 4; msgreq_class->classref = atoi(classref) + 1 + (msgreq_class->lcr<<8); msgreq_class->dir = OAI_NW_DRV_DIRECTION_RECEIVE; msgreq_class->fct = OAI_NW_DRV_FCT_QOS_SEND; msgreq_class->daddr.ipv4 = saddr_ipv4; msgreq_class->saddr.ipv4 = daddr_ipv4; msgreq_class->dplen = splen; msgreq_class->splen = dplen; printf("OAI_NW_DRV_MSG_CLASS_ADD_REQUEST: OAI_NW_DRV_DIRECTION_RECEIVE RB %d LCR %d ClassRef %d ", msgreq_class->rab_id, msgreq_class->lcr, msgreq_class->classref); printf("IPV4: Source = %d.%d.%d.%d/%d ", NIPADDR(msgreq_class->saddr.ipv4), msgreq_class->splen); printf("IPV4: Dest = %d.%d.%d.%d/%d\n", NIPADDR(msgreq_class->daddr.ipv4), msgreq_class->dplen); gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); } if (saddr_ipv6set == 1) { msgreq_class = (struct oai_nw_drv_msg_class_add_request *)(gifr.msg); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->version = 6; msgreq_class->dplen = dplen; msgreq_class->splen = splen; if (dscpset==0) msgreq_class->dscp = 0; else msgreq_class->dscp = atoi(dscp); msgreq_class->classref = atoi(classref) + (msgreq_class->lcr<<8); msgreq_class->dir = OAI_NW_DRV_DIRECTION_SEND; msgreq_class->fct = OAI_NW_DRV_FCT_QOS_SEND; // TO BE FIXED WHEN WE CAN SPECIFY A PROTOCOL-based rule msgreq_class->protocol = OAI_NW_DRV_PROTOCOL_DEFAULT; memcpy(&msgreq_class->saddr.ipv6,&saddr_ipv6,16); memcpy(&msgreq_class->daddr.ipv6,&daddr_ipv6,16); printf("OAI_NW_DRV_MSG_CLASS_ADD_REQUEST: OAI_NW_DRV_DIRECTION_SEND RB %d LCR %d ClassRef %d ", msgreq_class->rab_id, msgreq_class->lcr, msgreq_class->classref); printf("IPV6: Source = %x:%x:%x:%x:%x:%x:%x:%x/%d ", NIP6ADDR(&msgreq_class->saddr.ipv6), msgreq_class->splen); printf("IPV6: Dest = %x:%x:%x:%x:%x:%x:%x:%x/%d\n", NIP6ADDR(&msgreq_class->daddr.ipv6), msgreq_class->dplen); gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->dplen = splen; msgreq_class->splen = dplen; msgreq_class->classref = atoi(classref) + 1 + (msgreq_class->lcr<<8); msgreq_class->dir = OAI_NW_DRV_DIRECTION_RECEIVE; memcpy(&msgreq_class->daddr.ipv6,&saddr_ipv6,16); memcpy(&msgreq_class->saddr.ipv6,&daddr_ipv6,16); printf("OAI_NW_DRV_MSG_CLASS_ADD_REQUEST: OAI_NW_DRV_DIRECTION_RECEIVE RB %d LCR %d ClassRef %d ", msgreq_class->rab_id, msgreq_class->lcr, msgreq_class->classref); printf("IPV6: Source = %x:%x:%x:%x:%x:%x:%x:%x/%d ", NIP6ADDR(&msgreq_class->saddr.ipv6), msgreq_class->splen); printf("IPV6: Dest = %x:%x:%x:%x:%x:%x:%x:%x/%d\n", NIP6ADDR(&msgreq_class->daddr.ipv6), msgreq_class->dplen); gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); } if (mpls_inlabelset == 1) { msgreq_class = (struct oai_nw_drv_msg_class_add_request *)(gifr.msg); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->version = OAI_NW_DRV_MPLS_VERSION_CODE; if (dscpset==0) msgreq_class->dscp=0; else msgreq_class->dscp=atoi(dscp); msgreq_class->classref = atoi(classref) + (msgreq_class->lcr<<8); //msgreq_class->classref = 4 + (msgreq_class->lcr<<3); msgreq_class->dir=OAI_NW_DRV_DIRECTION_SEND; msgreq_class->fct=OAI_NW_DRV_FCT_QOS_SEND; // TO BE FIXED WHEN WE CAN SPECIFY A PROTOCOL-based rule msgreq_class->protocol = OAI_NW_DRV_PROTOCOL_DEFAULT; mpls_outlabel = atoi(mpls_outgoinglabel); printf("Setting MPLS outlabel %d with exp %d\n",mpls_outlabel,msgreq_class->dscp); msgreq_class->daddr.mpls_label = mpls_outlabel; gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); msgreq_class->classref = atoi(classref) + 1 + (msgreq_class->lcr<<8); //msgreq_class->classref = 5 + (msgreq_class->lcr<<3); msgreq_class->dir=OAI_NW_DRV_DIRECTION_RECEIVE; // TO BE FIXED WHEN WE CAN SPECIFY A PROTOCOL-based rule msgreq_class->protocol = OAI_NW_DRV_PROTOCOL_DEFAULT; mpls_inlabel = atoi(mpls_incominglabel); printf("Setting MPLS inlabel %d with exp %d\n",mpls_inlabel,msgreq_class->dscp); msgreq_class->daddr.mpls_label = mpls_inlabel; gifr.type = OAI_NW_DRV_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); } } else if (action == DEL_RB) { gifr.type = OAI_NW_DRV_MSG_RB_RELEASE_REQUEST; err=ioctl(fd, OAI_NW_DRV_IOCTL_RRM, &gifr); } }