int handle_snmp_event(struct oflops_context * ctx, struct snmp_event * se) { netsnmp_variable_list *vars; int len = 1024; char msg[1024], log[1024]; struct timeval now; int i; gettimeofday(&now, NULL); for(vars = se->pdu->variables; vars; vars = vars->next_variable) { snprint_value(msg, len, vars->name, vars->name_length, vars); if((vars->name_length == ctx->cpuOID_len) && (memcmp(vars->name, ctx->cpuOID, ctx->cpuOID_len * sizeof(oid)) == 0) ) { snprintf(log, len, "cpu : %s %%", msg); oflops_log(now, SNMP_MSG, log); } else { for(i=0;i<ctx->n_channels;i++) { if((vars->name_length == ctx->channels[i].inOID_len) && (memcmp(vars->name, ctx->channels[i].inOID, ctx->channels[i].inOID_len * sizeof(oid)) == 0) ) { snprintf(log, len, "port %d : rx %s pkts", (int)ctx->channels[i].outOID[ctx->channels[i].outOID_len-1], msg); oflops_log(now, SNMP_MSG, log); break; } if((vars->name_length == ctx->channels[i].outOID_len) && (memcmp(vars->name, ctx->channels[i].outOID, ctx->channels[i].outOID_len * sizeof(oid))==0) ) { snprintf(log, len, "port %d : tx %s pkts", (int)ctx->channels[i].outOID[ctx->channels[i].outOID_len-1], msg); oflops_log(now, SNMP_MSG, log); break; } } //for }// if cpu }// variable iterator return 0; }
/** Handle pcap event. * @param ctx pointer to opaque context * @param pe pcap event * @param ch enumeration of channel that pcap event is triggered */ int handle_pcap_event(struct oflops_context *ctx, struct pcap_event * pe, oflops_channel_name ch) { struct pktgen_hdr *pktgen; int dir, len; struct ofp_header *ofp; struct pcap_event *ofp_msg; struct ofp_error_msg *err_p = NULL; char msg[1024]; if (ch == OFLOPS_CONTROL) { dir = append_data_to_flow(pe->data,pe->pcaphdr); while(contains_next_msg(dir) > 0) { len = get_next_msg(dir, &ofp_msg); ofp = (struct ofp_header *)ofp_msg->data; switch(ofp->type) { case OFPT_FLOW_MOD: if (send_false_mod) { if(send_mod) { memcpy(&true_modification, &pe->pcaphdr.ts, sizeof(struct timeval)); } else { memcpy(&false_modification, &pe->pcaphdr.ts, sizeof(struct timeval)); } } if(send_mod) { oflops_log(pe->pcaphdr.ts,OFPT_FLOW_MOD_ADD, "flow modification send"); } break; case OFPT_ECHO_REQUEST: if(ntohl(ofp->xid) < 100) memcpy(&ofp_ping_timestamp[ntohl(ofp->xid)], &pe->pcaphdr.ts, sizeof(struct timeval)); break; case OFPT_ECHO_REPLY: if(ntohl(ofp->xid) < 100 && ntohl(ofp->xid) > 0) { delay[ntohl(ofp->xid)] = time_diff(&ofp_ping_timestamp[ntohl(ofp->xid)], &pe->pcaphdr.ts); snprintf(msg, 1024, "%d", time_diff(&ofp_ping_timestamp[ntohl(ofp->xid)], &pe->pcaphdr.ts)); oflops_log(pe->pcaphdr.ts, OFPT_ECHO_REPLY_MSG, msg); } break; case OFPT_ERROR: err_p = (struct ofp_error_msg *)ofp; if(send_false_mod) { delay_false_modificaton = time_diff(&false_modification, &pe->pcaphdr.ts); } else { snprintf(msg, 1024, "%d:%d", ntohs(err_p->type), ntohs(err_p->code)); oflops_log(pe->pcaphdr.ts, OFPT_ERROR_MSG, msg); fprintf(stderr, "OFPT_ERROR_MSG:%s\n", msg); break; } } } } else if ((ch == OFLOPS_DATA1) || (ch == OFLOPS_DATA2) || (ch == OFLOPS_DATA3)) { struct flow fl; pktgen = extract_pktgen_pkt(pe->data, pe->pcaphdr.caplen, &fl); if((ch == OFLOPS_DATA3) && (!first_pkt)) { delay_modificaton = time_diff(&true_modification, &pe->pcaphdr.ts); oflops_log(pe->pcaphdr.ts, GENERIC_MSG, "first packet on new port"); first_pkt = 1; } if(htonl(pktgen->seq_num) % 100000 == 0) printf("data packet received %d\n", htonl(pktgen->seq_num)); struct entry *n1 = malloc(sizeof(struct entry)); n1->snd.tv_sec = htonl(pktgen->tv_sec); n1->snd.tv_usec = htonl(pktgen->tv_usec); memcpy(&n1->rcv, &pe->pcaphdr.ts, sizeof(struct timeval)); n1->id = htonl(pktgen->seq_num); n1->ch = ch; TAILQ_INSERT_TAIL(&head, n1, entries); } return 0; }
/** Initialization * @param ctx pointer to opaque context */ int start(struct oflops_context * ctx) { struct flow *fl = (struct flow*)xmalloc(sizeof(struct flow)); fl_probe = (struct flow*)xmalloc(sizeof(struct flow)); void *b; //somewhere to store message data int res, len, i; struct timeval now; struct in_addr ip_addr; //init measurement queue TAILQ_INIT(&head); //init logging service msg_init(); //log when I start module gettimeofday(&now, NULL); oflops_log(now,GENERIC_MSG , "Intializing module openflow_action_measurement"); oflops_log(now,GENERIC_MSG , cli_param); //make filedescriptor blocking int saved_flags = fcntl(ctx->control_fd, F_GETFL); fcntl(ctx->control_fd, F_SETFL, saved_flags & ~O_NONBLOCK); make_ofp_hello(&b); //res = oflops_send_of_mesgs(ctx, b, sizeof(struct ofp_hello)); res = write(ctx->control_fd, b, sizeof(struct ofp_hello)); free(b); // send a feature request to see what the switch can do and os that the connection // is kept open. make_ofp_feat_req(&b); //res = oflops_send_of_mesgs(ctx, b, sizeof(struct ofp_hello)); res = write(ctx->control_fd, b, sizeof(struct ofp_hello)); free(b); //send a message to clean up flow tables. printf("cleaning up flow table...\n"); res = make_ofp_flow_del(&b); res = write(ctx->control_fd, b, res); free(b); /** * Send flow records to start routing packets. */ printf("Sending new flow rules...\n"); bzero(fl, sizeof(struct flow)); printf("table value:%d\n", table); if(table == 0) fl->mask = 0; //if table is 0 the we generate an exact match */ else fl->mask = OFPFW_IN_PORT | OFPFW_DL_VLAN | OFPFW_TP_DST; fl->in_port = htons(ctx->channels[OFLOPS_DATA2].of_port); fl->dl_type = htons(ETHERTYPE_IP); fl->dl_src[0] = 00; fl->dl_src[1] = 0x1e; fl->dl_src[2] = 0x68; fl->dl_src[3] = 0x9a; fl->dl_src[4] = 0xc5; fl->dl_src[5] = 0x75; fl->dl_dst[0] = 00; fl->dl_dst[1] = 0x15; fl->dl_dst[2] = 0x17; fl->dl_dst[3] = 0x7b; fl->dl_dst[4] = 0x92; fl->dl_dst[5] = 0x0a; fl->dl_vlan = 0xffff; fl->nw_proto = IPPROTO_UDP; fl->nw_src = inet_addr("10.1.1.1"); fl->nw_dst = inet_addr("10.1.1.2"); fl->tp_src = htons(8080); fl->tp_dst = htons(8080); len = make_ofp_flow_add(&b, fl, ctx->channels[OFLOPS_DATA1].of_port, 1, 1200); res = write(ctx->control_fd, b, len); free(b); //storelocally the applied rule of the data stream memcpy(fl_probe, fl, sizeof(struct flow)); ip_addr.s_addr = inet_addr(network); ip_addr.s_addr = ntohl(ip_addr.s_addr); fl->in_port = htons(ctx->channels[OFLOPS_DATA1].of_port); fl->dl_vlan = 0xffff; fl->dl_src[5] = 0x74; fl->dl_dst[0] = 00; fl->dl_dst[1] = 0x1e; fl->dl_dst[2] = 0x68; fl->dl_dst[3] = 0x9a; fl->dl_dst[4] = 0xc5; fl->dl_dst[5] = 0x75; fl->mask = 0; for(i=0; i< flows; i++) { ip_addr.s_addr += 1; fl->nw_dst = htonl(ip_addr.s_addr); len = make_ofp_flow_add(&b, fl, ctx->channels[OFLOPS_DATA2].of_port, 1, 1200); res = write(ctx->control_fd, b, len); free(b); } len = make_ofp_port_get_stat(&b); free(b); saved_flags = fcntl(ctx->control_fd, F_GETFL); fcntl(ctx->control_fd, F_SETFL, saved_flags & O_NONBLOCK); /** * Shceduling events */ //SND_FALSE_ACT gettimeofday(&now, NULL); add_time(&now, 20, 0); oflops_schedule_timer_event(ctx,&now, SND_FALSE_ACT); //send the flow modyfication command in 30 seconds. gettimeofday(&now, NULL); add_time(&now, 30, 0); oflops_schedule_timer_event(ctx,&now, SND_ACT); //action of ping request gettimeofday(&now, NULL); add_time(&now, 1, 0); oflops_schedule_timer_event(ctx,&now, OFP_PING); //get port and cpu status from switch gettimeofday(&now, NULL); add_time(&now, 10, 0); oflops_schedule_timer_event(ctx,&now, SNMPGET); //end process gettimeofday(&now, NULL); add_time(&now, 60, 0); oflops_schedule_timer_event(ctx,&now, BYESTR); return 0; }
int destroy(struct oflops_context *ctx) { char msg[1024]; struct timeval now; FILE *out = fopen(logfile, "w"); struct entry *np; long long t[3], t_sq[3], mean, std; int count[3], min_id[3], max_id[3]; int ch; float loss; int xid; gettimeofday(&now, NULL); printf("destroying code\n"); snprintf(msg, 1024, "OFPT_ERROR_DELAY:%lld", delay_false_modificaton); oflops_log(now, GENERIC_MSG, msg); snprintf(msg, 1024, "OFPT_INSERT_DELAY:%lld", delay_modificaton); oflops_log(now, GENERIC_MSG, msg); for(ch = 0; ch < ctx->n_channels-1; ch++) { count[ch] = 0; min_id[ch] = INT_MAX; max_id[ch] = INT_MIN; t[ch] = 0; t_sq[ch] = 0; } for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next) { if(fprintf(out, "%lu;%lu.%06lu;%lu.%06lu;%d\n", (long unsigned int)np->id, (long unsigned int)np->snd.tv_sec, (long unsigned int)np->snd.tv_usec, (long unsigned int)np->rcv.tv_sec, (long unsigned int)np->rcv.tv_usec, np->ch) < 0) perror_and_exit("fprintf fail", 1); ch = np->ch - 1; count[ch]++; min_id[ch] = (np->id < min_id[ch])?np->id:min_id[ch]; max_id[ch] = (np->id > max_id[ch])?np->id:max_id[ch]; t[ch] += time_diff(&np->snd, &np->rcv); t_sq[ch] += time_diff(&np->snd, &np->rcv)*time_diff(&np->snd, &np->rcv); free(np); } for(ch = 0; ch < ctx->n_channels-1; ch++) { if(count[ch] == 0) continue; mean = t[ch]/count[ch]; std = (t_sq[ch]/count[ch]) - mean*mean; if(std >= 0) std = sqrt(std); else std = LONG_MAX; loss = (float)count[ch]/(float)(max_id[ch] - min_id[ch]); snprintf(msg, 1024, "statistics:port:%d:%lld:%lld:%.4f:%d", ctx->channels[ch + 1].of_port, mean, std, loss, count[ch]); oflops_log(now, GENERIC_MSG, msg); } t[0] = 0; t_sq[0] = 0; for (xid = 1 ; xid < trans_id; xid++) { t[0] +=delay[xid]; t_sq[0] += delay[xid]*delay[xid]; } std = (t_sq[0]/trans_id) - mean*mean; std = (std >= 0)?sqrt(std):LONG_MAX; snprintf(msg, 1024, "ofp_echo_statistics:%lld:%lld", t[0]/trans_id, std); oflops_log(now, GENERIC_MSG, msg); return 0; }
int ofp_msg_log(const void *b, struct pcap_pkthdr hdr) { size_t len = hdr.caplen; struct ofp_error_msg *err_p = NULL; struct ofp_header *ofp = NULL; int ret = GENERIC_MSG; struct flow fl; struct ofp_stats_request *reqp = NULL; struct ofp_stats_reply *repp = NULL; int count = 0; //random inary value to distinguish wether the packet is from the larger //port number to the lowest or vice versa. int dir = 0; //client to server //since this is a packet capture, strip packet from all the l1-l4 headers. int start = parse_ip_packet_header(b, len, &fl); if(ntohs(fl.tp_src) < ntohs(fl.tp_dst)) dir = 1; //server to client if(len - start == 0) { //printf("no data in tcp packet\n"); return -1; } //printf("initial length: %d, packet length = %d, direction: %d\n", content_length[dir], len - start, dir); b += start; len -= start; while(buff_size[dir] < content_length[dir] + len) { buff_size[dir] += INITIAL_BUF_SIZE; buff[dir] = realloc(buff[dir], buff_size[dir]); } //append new packet to the buffer memcpy(buff[dir] + content_length[dir], b, len); content_length[dir] += len; ofp = (struct ofp_header *)buff[dir]; while((content_length[dir] - count >= sizeof(struct ofp_header)) && (ntohs(ofp->length) <= (content_length[dir] - count))) { //printf("start length: %d, count: %d, length: %d\n", ntohs(ofp->length), count, (content_length[dir] - count)); assert(ntohs(ofp->length)); // exit(1); switch(ofp->type) { case OFPT_HELLO: //printf("ofp hello\n"); oflops_log(hdr.ts, OFPT_HELLO_MSG, "hello message"); ret = OFPT_HELLO_MSG; break; case OFPT_STATS_REQUEST: reqp = (struct ofp_stats_request *) ofp; //printf("stats request\n"); if (ntohs(reqp->type) == OFPST_FLOW) { oflops_log(hdr.ts, OFPT_STATS_REQUEST_FLOW, "stats request send"); ret = OFPT_STATS_REQUEST_FLOW; } break; case OFPT_STATS_REPLY: repp = (struct ofp_stats_reply *) ofp; printf("stats reply\n"); if (ntohs(repp->type) == OFPST_FLOW) { oflops_log(hdr.ts, OFPT_STATS_REPLY_FLOW, "flow stats reply received"); ret = OFPT_STATS_REPLY_FLOW; } else if (ntohs(repp->type) == OFPST_PORT) { oflops_log(hdr.ts, OFPT_STATS_REPLY_PORT, "port stats reply received"); ret = OFPT_STATS_REPLY_PORT; } break; case OFPT_ERROR: err_p = (struct ofp_error_msg *)ofp; char *msg = xmalloc(sizeof("OFPT_ERROR(type: XXXXXXXXXX, code: XXXXXXXXXX)")); sprintf(msg, "OFPT_ERROR(type: %d, code: %d)", ntohs(err_p->type), ntohs(err_p->code)); oflops_log(hdr.ts, OFPT_ERROR_MSG, msg); ret = OFPT_ERROR_MSG; break; //default: // printf("msg type: %d, length: %d, code: %d\n", ofp->type, ntohs(ofp->length), count); } count += ntohs(ofp->length); ofp = (struct ofp_header *)(buff[dir] + count); //printf("end length: %d, count: %d, length: %d\n", ntohs(ofp->length), count, (content_length[dir]- count)); } //need to rearrange buffer if(count < content_length[dir]) { memmove(buff[dir], buff[dir] + count, (content_length[dir] - count)); content_length[dir] -= count; } else content_length[dir] = 0; return ret; }