source: ResearchApps/Measurement/warpnet_coprocessors/phy_logger/phy_logger.c

Last change on this file was 1601, checked in by murphpo, 13 years ago

adding phy_logger warpnet coprocessor

  • Property svn:executable set to *
File size: 17.4 KB
Line 
1#include <assert.h>
2#include <unistd.h>
3#include <signal.h>
4#include <stdio.h>
5#include <string.h>
6#include <stdlib.h>
7#include <pcap.h>
8#include "phy_logger.h"
9#include <sys/time.h>
10#include <netinet/in.h>
11
12//Global variables
13
14//Lookup table of numbers of ones in binary representations of each 8-bit value
15const unsigned char ones_in_chars[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
16
17//PCAP session handle (used by pcap Rx and Tx threads)
18pcap_t *pcap_handle;
19
20//Network device for PCAP (en0 = Ethernet; en5 = USB Ethernet)
21char* pcap_device;
22
23const char debug = 0;
24
25//Number of WARP nodes
26unsigned int numWARPnodes;
27
28unsigned int log_param0;
29unsigned int log_param1;
30unsigned int log_param2;
31unsigned int log_param3;
32unsigned short berLog_fileSuffix;
33
34//WARPnet structs
35warpnetEthernetPktHeader txEthPktHdr;
36warpnetControllerGroup groupStruct;
37
38unsigned char txEthPktBuf[MAX_ETHPKTSIZE];
39                         
40//This "node's" ID (for talking to the warpnet server as if it were a node)
41unsigned char myID;
42
43//Array of log file handles, one per node
44FILE* log_fds[MAX_NUMWARPNODES];
45
46//Time structs for scheduled node updates
47struct timeval currentTime;
48struct timezone theTimezone;
49
50void pcap_pktRx_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
51   
52    warpnetEthernetPktHeader* ethPktHdr;
53   
54    ethPktHdr = (warpnetEthernetPktHeader*)packet;
55   
56    if(ethPktHdr->ethType == WARPNET_ETHTYPE_SVR2NODE)
57        ProcessServerMessage(args, header, packet);
58    else if(ethPktHdr->ethType == WARPNET_ETHTYPE_NODE2COPROC)
59        ProcessWARPnodeMessage(args, header, packet);
60    else
61        printf("pcap_pktRx_handler: Unknown ethertype: 0x%04x\n", ethPktHdr->ethType);
62   
63    return;
64}
65
66void ProcessServerMessage(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
67   
68    void* rxPktPtr;
69   
70    int i, numRxStructs;
71    unsigned char rxSeqNum, theStructID;
72   
73    //Typed pointers for interpreting received structs
74    warpnetEthernetPktHeader* pktHeader;
75    warpnetControllerGroup* groupStructCopy;
76    warpnetCommand* commandStruct;
77    warpnetLogParams* logParams;
78   
79    unsigned short berLog_fileSuffix_new;
80   
81    //Local ACK struct, used to send responses to the server
82    warpnetAck ackStruct;
83   
84    //Interpret the received bytes as an Ethernet packet
85    pktHeader = (warpnetEthernetPktHeader*)packet;
86   
87    if((pktHeader->ethType) != WARPNET_ETHTYPE_SVR2NODE) {
88        //Should never happen; all management packets are type WARPNET_ETHTYPE_SVR2NODE
89        return;
90    }
91   
92    numRxStructs = pktHeader->numStructs;
93    rxSeqNum = pktHeader->seqNum;
94   
95    //Initialize the rx pointer to the first byte past the Ethernet header
96    rxPktPtr = (void*)(packet + sizeof(warpnetEthernetPktHeader));
97   
98    //Iterate over each pair of warpnetControllerGroup / otherStruct in the server message
99    for(i=0; i<numRxStructs; i++) {
100       
101        if( ( ((int)rxPktPtr) - ((int)packet) ) >= header->len) {
102            printf("Error! Mgmt pktLength too short for numStructs\n");
103            return;
104        }
105       
106        //Alternate structs (starting with the first) are always warpnetControllerGroup
107        groupStructCopy = (warpnetControllerGroup*)rxPktPtr;
108        rxPktPtr += sizeof(warpnetControllerGroup);
109       
110        //Extract the first byte of the actual struct and interpret as the structID
111        theStructID = *( (unsigned char *)rxPktPtr );
112        //xil_printf("Mgmt Pkt: StructID=0x%x\r\n", theStructID);
113       
114        switch(theStructID)
115        {
116            case STRUCTID_COMMAND:
117                commandStruct = (warpnetCommand*)rxPktPtr;
118                rxPktPtr += sizeof(warpnetCommand);
119               
120                if((commandStruct->nodeID) == myID) {
121                   
122                    //Send an ACK struct back to the server
123                    ackStruct.structID = STRUCTID_COMMAND_ACK;
124                    ackStruct.nodeID = myID;
125                    ackStruct.cmdID = commandStruct->cmdID;
126                   
127                    SendStructToServer(groupStructCopy, &ackStruct);
128                   
129                    //Process the received struct
130                    //processCommand(commandStruct);
131                }
132                break;
133            case STRUCTID_LOGPARAMS:
134                logParams = (warpnetLogParams*)rxPktPtr;
135                rxPktPtr += sizeof(warpnetLogParams);
136               
137                if((logParams->nodeID) == myID) {
138
139                    berLog_fileSuffix_new = htons(logParams->fileSuffix); //Endian swap, since it's used internally, not just written to the file
140
141                    log_param0 = logParams->param0;
142                    log_param1 = logParams->param1;
143                    log_param2 = logParams->param2;
144                    log_param3 = logParams->param3;
145                   
146                    if(berLog_fileSuffix_new != berLog_fileSuffix) {
147                        berLog_fileSuffix = berLog_fileSuffix_new;
148                        SetupLogFiles();
149                    }
150                   
151                    if(debug > 1) printf("Got LOGPARAMS: 0=%d, 1=%d, 2=%d, 3=%d\n", htonl(log_param0), htonl(log_param1), htonl(log_param2), htonl(log_param3));
152                   
153                    //Send an ACK struct back to the server
154                    ackStruct.structID = STRUCTID_LOGPARAMS_ACK;
155                    ackStruct.nodeID = myID;
156                    ackStruct.cmdID = 0;
157                   
158                    SendStructToServer(groupStructCopy, &ackStruct);
159                }
160                break;
161               
162            default:
163                //Unrecognized structID; do nothing
164                //printf("Unknown structID: 0x%x\n", theStructID);
165                break;
166        }//END switch(theStructID)
167       
168       
169    }//END for(0...numStructs-1)
170   
171    return;
172}
173
174void ProcessWARPnodeMessage(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
175{
176    //printf("ProcessWARPnodeMessage: Got a WARP node update\n");
177
178    //Packets from the WARP node must have this sturcture; indicies are bytes:
179    // warpnetEthernetPktHeader struct first:
180    //  0-5: Source MAC address (last nibble assumed to be nodeID)
181    //  6-11: Destination MAC address
182    //  12-13: Ethertype = WARPNET_ETHTYPE_NODE2BER
183    //  14-15: Number of bytes in full packet, including this header
184    //  16: Number of WARPNet structs in packet
185    //  17: seqNum (for what?)
186    // 18:... beginning of warpnet structs
187
188    void* rxPktPtr;
189   
190    int i, j, numRxStructs;
191    unsigned char theStructID;
192
193    unsigned char inner_structID;
194    unsigned short inner_numStructs;
195    unsigned int concat_trialIndex;
196   
197    //Typed pointers for interpreting received structs
198    warpnetEthernetPktHeader* pktHeader;
199    warpnetConcatStruct* ptr_concatStruct;
200    warpnetRTObserve* ptr_rtObserve;
201    warpnetCommand* ptr_commandStruct;
202    warpnetRxPHYdump* ptr_rxPHYdumpStruct;
203   
204    unsigned char ethpkt_nodeID;
205    unsigned int ethpkt_len;
206   
207    unsigned short tmp_relNode;
208   
209    if( (header->len) < (sizeof(warpnetEthernetPktHeader))) {
210        printf("ProcessWARPnodeMessage: pcap captured too short a packet! (%d bytes)\n", (header->len));
211        return;
212    }
213   
214    //Intrepret the received packet's header
215    pktHeader = (warpnetEthernetPktHeader*)packet;
216    ethpkt_len = htons(pktHeader->pktLength);
217    ethpkt_nodeID = ((pktHeader->srcAddr[5]) & 0xF);
218   
219    //Sanity-check the received Ethernet header
220    if( (header->len) < ethpkt_len) {
221        printf("ProcessWARPnodeMessage: pcap captured too short a packet! (%d bytes captured, ethPktHdr.len claimed %d)\n", (header->len), ethpkt_len);
222        return;
223    }
224
225    if((ethpkt_nodeID >= numWARPnodes)) {
226        printf("ProcessWARPnodeMessage: invalid nodeID! nodeID=%d\n", ethpkt_nodeID);
227        return;
228    }
229
230    if((pktHeader->ethType) != WARPNET_ETHTYPE_NODE2COPROC) {
231        //Should never happen; pcap should only accept COPROC packets
232        return;
233    }
234   
235    numRxStructs = pktHeader->numStructs;
236
237    //Initialize the rx pointer to the first byte past the Ethernet header
238    rxPktPtr = (void*)(packet + sizeof(warpnetEthernetPktHeader));
239   
240    //Iterate over each pair of warpnetControllerGroup / otherStruct in the server message
241    for(i=0; i<numRxStructs; i++) {
242       
243        if( ( ((int)rxPktPtr) - ((int)packet) ) >= (header->len)) {
244            printf("Error! pktLength too short for numStructs\r\n");
245            return;
246        }
247       
248        //Extract the first byte of the actual struct and interpret as the structID
249        theStructID = *( (unsigned char *)rxPktPtr );
250       
251        switch(theStructID)
252        {
253            case STRUCTID_COMMAND:
254                ptr_commandStruct = (warpnetCommand*)rxPktPtr;
255                rxPktPtr += sizeof(warpnetCommand);
256               
257                if((ptr_commandStruct->nodeID) == myID) {
258                    //FIXME: do something with the commandStruct
259                }
260                break;
261            case STRUCTID_RXPHYDUMP:
262                ptr_rxPHYdumpStruct = (warpnetRxPHYdump*)rxPktPtr;
263                rxPktPtr += sizeof(warpnetRxPHYdump);
264               
265                if( (ptr_rxPHYdumpStruct->nodeID) < numWARPnodes) {
266                    LogRxPHYDump(ptr_rxPHYdumpStruct, log_fds[(ptr_rxPHYdumpStruct->nodeID)]);
267                }
268               
269                break;
270            case STRUCTID_CONCAT:
271                ptr_concatStruct = (warpnetConcatStruct*)rxPktPtr;
272                concat_trialIndex = htonl(ptr_concatStruct->trialIndex);
273                inner_numStructs = htons(ptr_concatStruct->numStructs);
274
275                rxPktPtr = &(ptr_concatStruct->innerStructs);
276
277                if(debug > 1) printf("Got ConcatStruct with %d inner structs, trial index %d\n", inner_numStructs, concat_trialIndex);
278
279                for(j=0; j<inner_numStructs; j++) {
280                    inner_structID = *( (unsigned char*)rxPktPtr);
281
282                    if(inner_structID == STRUCTID_RTOBSERVE) {
283                        ptr_rtObserve = (warpnetRTObserve*)rxPktPtr;
284                       
285                        tmp_relNode = (ptr_rtObserve->relNode);
286                       
287                        if(log_fds[ethpkt_nodeID] != NULL) {
288                            LogRTobserve(ptr_rtObserve, concat_trialIndex, log_fds[ethpkt_nodeID]);
289                        }
290                        else {
291                            printf("Error! File closed for node %d\n", ethpkt_nodeID);
292                            return;
293                        }
294                        rxPktPtr += sizeof(warpnetRTObserve);
295                    }
296                    else {
297                        printf("\tUnknown inner_structID: 0x%x\n", inner_structID);
298                        break;
299                    }
300                }//for concatStruct.numStructs
301               
302                fflush(log_fds[ethpkt_nodeID]);
303                break;//case STRUCTID_CONCAT:
304        }
305    }//for ethPkt.numStructs
306   
307    return;
308}
309
310void SendStructToServer(warpnetControllerGroup* theGroupStruct, void *theStruct) {
311   
312    unsigned char structID;
313    void* structPtr;
314   
315    int structLen = 0;
316    int rv;
317   
318    structPtr = theStruct;
319   
320    structID = *( (unsigned char *)theStruct);
321    void* txPktPtr;
322   
323    switch(structID)
324    {
325        case STRUCTID_LOGPARAMS_ACK:
326            structLen = sizeof(warpnetAck);
327            structPtr = theStruct;
328            break;
329           
330        default:
331            printf("SendStructToServer: Unknown structID! (0x%x)\n", structID);
332            break;
333    }
334   
335    if(structLen > 0)
336    {
337        txEthPktHdr.ethType = WARPNET_ETHTYPE_NODE2SVR;
338        txEthPktHdr.pktLength = sizeof(warpnetEthernetPktHeader) + sizeof(warpnetControllerGroup) + structLen;
339        txEthPktHdr.numStructs = 1;
340        txEthPktHdr.seqNum = 0;
341       
342        txPktPtr = &txEthPktBuf;
343        memcpy(txPktPtr, &txEthPktHdr, sizeof(warpnetEthernetPktHeader));
344        memcpy(txPktPtr+sizeof(warpnetEthernetPktHeader), theGroupStruct, sizeof(warpnetControllerGroup));
345        memcpy(txPktPtr+sizeof(warpnetEthernetPktHeader)+sizeof(warpnetControllerGroup), structPtr, structLen);
346       
347        rv = pcap_inject(pcap_handle, (void *)txPktPtr, (txEthPktHdr.pktLength) );
348       
349        if(rv < 0){
350            pcap_perror(pcap_handle, "");
351            printf("Error on pcap_inject!\n");
352        }
353    }
354   
355    return;
356}
357
358int LogRxPHYDump(warpnetRxPHYdump* ptr_rxPHYdumpStruct, FILE* logFile) {
359
360    int writeLen, rv;
361   
362    //Write the server-provided params first
363    rv = fwrite((void *)&log_param0, sizeof(unsigned int), 1, logFile); if(rv<1) {printf("Error writing log! (0; write %d)\n", rv); return -1;}
364    rv = fwrite((void *)&log_param1, sizeof(unsigned int), 1, logFile); if(rv<1) {printf("Error writing log! (1; write %d)\n", rv); return -1;}
365    rv = fwrite((void *)&log_param2, sizeof(unsigned int), 1, logFile); if(rv<1) {printf("Error writing log! (2; write %d)\n", rv); return -1;}
366    rv = fwrite((void *)&log_param3, sizeof(unsigned int), 1, logFile); if(rv<1) {printf("Error writing log! (3; write %d)\n", rv); return -1;}
367   
368    writeLen = sizeof(warpnetRxPHYdump);
369   
370    if( (ptr_rxPHYdumpStruct->includedData) & RXPHYDUMP_INCLUDE_EVMPERSC) {
371        writeLen += RXPHYDUMP_SIZE_EVMPERSC;
372    }
373    if( (ptr_rxPHYdumpStruct->includedData) & RXPHYDUMP_INCLUDE_EVMPERSYM) {
374        writeLen += RXPHYDUMP_SIZE_EVMPERSYM;
375    }
376    if( (ptr_rxPHYdumpStruct->includedData) & RXPHYDUMP_INCLUDE_CHANESTAA) {
377        writeLen += RXPHYDUMP_SIZE_CHANEST;
378    }
379    if( (ptr_rxPHYdumpStruct->includedData) & RXPHYDUMP_INCLUDE_CHANESTBA) {
380        writeLen += RXPHYDUMP_SIZE_CHANEST;
381    }
382
383    rv = fwrite((void *)ptr_rxPHYdumpStruct, sizeof(char), writeLen, logFile);
384    if(rv != writeLen) {
385        printf("LogRxPHYDump: Error writing log file; tried to write %d bytes; fwrite returned %d\n", writeLen, rv);
386        return -1;
387    }
388
389    fflush(logFile);
390    return 0;
391}
392
393int LogRTobserve(warpnetRTObserve* ptr_rtObserve, unsigned int trialIndex, FILE* logFile) {
394   
395    //trialIndex, sequenceNumber, pktType, srcNode, dstNode, relayNode, phystatus, macstate, RSSI, gain, local timestamp High, local timestamp Low, numPacketDet
396    fprintf(logFile, "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\r\n",\
397            trialIndex, \
398            htons(ptr_rtObserve->sequenceNumber), \
399            (ptr_rtObserve->srcNode), \
400            (ptr_rtObserve->destNode), \
401            (ptr_rtObserve->relNode), \
402            (ptr_rtObserve->pktType), \
403            (ptr_rtObserve->phystatus), \
404            (ptr_rtObserve->macstate), \
405            htons(ptr_rtObserve->rssi), \
406            htons(ptr_rtObserve->gain), \
407            htons(ptr_rtObserve->timeStampHigh), \
408            htonl(ptr_rtObserve->timeStampLow), \
409            htonl(ptr_rtObserve->packetDetCount) \
410            );
411    return 0;
412}
413
414//This code is based on the excellent libpcap examples at http://www.tcpdump.org/pcap.htm
415int SetupPCAP()
416{
417    char errbuf[PCAP_ERRBUF_SIZE];  // Error string
418    struct bpf_program fp;      // The compiled filter
419//  char filter_exp[19];
420    char filter_exp[43];
421    bpf_u_int32 mask;       // Our netmask
422    bpf_u_int32 net;        // Our IP
423   
424    fprintf(stdout, "Attaching to device %s\n", pcap_device);
425
426//  sprintf((char *)&filter_exp, "ether proto 0x%04x", WARPNET_ETHTYPE_NODE2COPROC);
427    sprintf((char *)&filter_exp, "(ether proto 0x%04x or ether proto 0x%04x)", WARPNET_ETHTYPE_NODE2COPROC, WARPNET_ETHTYPE_SVR2NODE);
428   
429    //Lookup properties for the network device
430    // pcap_device is a global variable, defined either by default or as a cmd line argument
431    if (pcap_lookupnet(pcap_device, &net, &mask, errbuf) == -1)
432    {
433        fprintf(stderr, "PCAP: Couldn't get netmask for device %s: %s\n", pcap_device, errbuf);
434        net = 0;
435        mask = 0;
436    }
437
438    // Open the session in promiscuous mode with a big enough buffer
439    pcap_handle = pcap_open_live(pcap_device, 65535, 1, 100, errbuf);
440   
441    if (pcap_handle == NULL)
442    {
443        fprintf(stderr, "PCAP: Couldn't open device %s: %s\n", pcap_device, errbuf);
444        return -2;
445    }
446   
447    // Compile and apply the filter
448    if (pcap_compile(pcap_handle, &fp, filter_exp, 0, net) == -1)
449    {
450        fprintf(stderr, "PCAP: Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle));
451        return -2;
452    }
453   
454    if (pcap_setfilter(pcap_handle, &fp) == -1)
455    {
456        fprintf(stderr, "PCAP: Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle));
457        return -2;
458    }
459   
460    fprintf(stdout, "Applied filter '%s'\n", filter_exp);
461
462    //Loop forever on received Ethernet frames
463    pcap_loop(pcap_handle, -1, (pcap_handler)pcap_pktRx_handler, NULL);
464
465    return 0;
466}
467
468int SetupLogFiles() {
469    int i;
470    char fileName[50];
471   
472    for(i=0; i<numWARPnodes; i++) {
473        sprintf(fileName, "logs/phylog_%04d_n%d.log", berLog_fileSuffix, i);
474
475        if(log_fds[i] != NULL)
476            fclose(log_fds[i]);
477
478        log_fds[i] = fopen(fileName, "w");
479
480        if(log_fds[i] == NULL) {
481            printf("Error creating log file\r\n");
482            return -1;
483        }
484    }
485
486    return 0;
487};
488   
489int main(int argc, char *argv[])
490{
491    printf("Starting WARP PHY Logger\n");
492
493    int i;
494    //Default number of WARP nodes; can be overridden on the command line
495    numWARPnodes = 3;
496
497    log_param0 = 0;
498    log_param1 = 0;
499    log_param2 = 0;
500    log_param3 = 0;
501
502    berLog_fileSuffix = 0;
503   
504    //Use the next-largest ID, after all the actual nodes
505    myID = 98;
506   
507    groupStruct.controllerID = 0;
508    groupStruct.controllerGrp = 0;
509    groupStruct.access = 1;
510    groupStruct.reserved0 = 0xA5;
511   
512    txEthPktHdr.ethType = WARPNET_ETHTYPE_NODE2SVR;
513    txEthPktHdr.srcAddr[0]=0x00;
514    txEthPktHdr.srcAddr[1]=0x50;
515    txEthPktHdr.srcAddr[2]=0xC2;
516    txEthPktHdr.srcAddr[3]=0x63;
517    txEthPktHdr.srcAddr[4]=0x3F;
518    txEthPktHdr.srcAddr[5]=0x80+myID;
519
520
521    //Linux RiceNet2 NIC
522    txEthPktHdr.dstAddr[0]=0x00;
523    txEthPktHdr.dstAddr[1]=0x50;
524    txEthPktHdr.dstAddr[2]=0xC2;
525    txEthPktHdr.dstAddr[3]=0x63;
526    txEthPktHdr.dstAddr[4]=0x3F;
527    txEthPktHdr.dstAddr[5]=0xFC;
528   
529/*
530 //Macbook #1
531 txEthPktHdr.dstAddr[0]=0x00;
532 txEthPktHdr.dstAddr[1]=0x17;
533 txEthPktHdr.dstAddr[2]=0xf2;
534 txEthPktHdr.dstAddr[3]=0xdb;
535 txEthPktHdr.dstAddr[4]=0x05;
536 txEthPktHdr.dstAddr[5]=0x07;
537*/
538   
539    if(argc == 1)
540    {   
541        //Set sensible defaults if the user forgets to provide arguments
542        pcap_device = "eth1";
543        printf("No cmd line params; Assuming pcapDevice: %s, numNodes: %d\n", pcap_device, numWARPnodes);
544    }
545    else if(argc == 2)
546    {
547        //User provided an Ethernet interface to use
548        pcap_device = argv[1];
549        printf("Cmd line params: pcapDevice: %s\nAssuming numNodes: %d\n", pcap_device, numWARPnodes);
550    }
551    else if(argc == 3)
552    {
553        //User provided an Ethernet interface to use and number of WARP nodes
554        pcap_device = argv[1];
555        numWARPnodes = atoi((char *)argv[2]);
556        printf("Cmd line params: pcapDevice: %s, numNodes: %d\n", pcap_device, numWARPnodes);
557    }
558    else
559    {
560        //User didn't provide good arguments; print usage and quit
561        printf("Usage: %s <Ethernet device> <number of WARP nodes>\nExamples:\n\t%s (defaults to interface eth1)\n\t%s eth1 3 (use interface eth1, 3 WARP nodes)", argv[0], argv[0], argv[0]);
562        return -1;
563    }
564
565    //Null out the file descriptors to start out
566    for(i=0; i<numWARPnodes; i++) {
567        log_fds[i] = NULL;
568    }
569       
570    if(SetupLogFiles() != 0) {
571        return -1;
572    }
573   
574    //Sets up the PCAP capture interface
575    // This function blocks, processing Ethernet packets forever
576    SetupPCAP();
577
578    return 0;
579}
Note: See TracBrowser for help on using the repository browser.