由pcap文件提取IPv6的flow数据

本文介绍了从大型 pcap 文件中提取IPv6流量数据的过程,包括使用MD5算法减少哈希冲突,从而提高数据处理效率。通过Visual Studio 2012实现,详细讨论了实现步骤、冲突解决策略以及最终结果。
摘要由CSDN通过智能技术生成

一、目标:

现有两个大学抓取的packet数据,分片成若干部分,需要从中抽取出流信息( 源mac地址、目的mac地址、源ip地址、目的IP地址、源端口、目的端口、vlan、协议类型、流首包时间、流末包时间、流总大小),并按文件中的packet顺序,将结果输出出来。

二、实现过程:

1、没有沟通好需求是个硬伤,直接导致前面几次提交结果不合格。
2、pcap是二进制文件,花了点时间研究pcap的文件结构和二进制文件的读写方式。
3、数据量非常大,第一组数据packet数约一千万,第二组有一亿以上,对内存分配是个考验。
4、一开始采用了顺序查找,速度非常慢,运行到后期,10秒只能遍历100组数据。在老师提示下采用了hash表来存储,速度果然不同凡响。
5、hash表关键字的选择:
(1)初期:观察了packet数据,发现源ip地址(SrcIP)不一样的情况比较多,因此哈希函数和关键字都直接用它了。冲突解决采用线性散列(加1)。
( 2)中期:初期的冲突还是太多了,到后面速度异常慢,因此哈希函数和关键字都改成了源mac地址、目的mac地址、源ip地址、目的IP地址、源端口、目的端口、vlan、协议类型的和(当然还要对hash表长取模),这么一来冲突小了不少。然而运行至文件末时速度仍然不够。
(3)后期:导师提示了md5算法,即Message Digest Algorithm MD5(消息摘要算法第五版),它的特点是:
①、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
②、容易计算:从原数据计算出MD5值很容易。
③、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
④、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
⑤、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
这就意味着用md5算法作为hash函数可以大大减少冲突(实际情况是基本不出现冲突),毕竟不同关键字算出来的值差异太大了(但并没有直接验证,只是通过运行时间间接得出的结论)。
6、运行时间:一百万个flow大概200s,这比顺序查找简直快了四五个量级。

三、代码

(运行环境为Visual Studio 2012)
主代码如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "md5.h"
#include<math.h>
#include<time.h>
#define N 13000000LL
#define NUM_OF_MAX_FLOW 13000000LL
static long long index[NUM_OF_MAX_FLOW]={
  0},FlowCnt=1;
typedef unsigned char uint8;
typedef struct{
    int TimeStart;
    int MicroSec;
    int Caplen;
    uint8 SrcMac[6];
    uint8 DstMac[6];
    uint8 SrcIP[4];
    uint8 DstIP[4];
    uint8 SrcPort[2];
    uint8 DstPort[2];
    uint8 VlanID[2];
    uint8 VlanType[2];
    uint8 Protocol;
    int FlowBytes;
}STREAM;
typedef struct{
    uint8 flag;
    double timeStart;
    double timeEnd;
    uint8 SrcMac[6];
    uint8 DstMac[6];
    uint8 SrcIP[4];
    uint8 DstIP[4];
    uint8 SrcPort[2];
    uint8 DstPort[2];
    uint8 VlanID[2];
    uint8 VlanType[2];
    uint8 Protocol;
    unsigned long FlowBytes;
    unsigned long PacketsNum;
}FLOW;
static FLOW FlowTable[NUM_OF_MAX_FLOW] = { 0 };
void writeHex(FILE *fw, uint8 *str, int n)
{
    int i;
    for (i = 0; i<n; i++){
        fprintf(fw, "%x%x", (str[i] - str[i] % 16) >> 4, str[i] % 16);
    }
    return;
}
int isEqual(uint8 *old,uint8 *now,int n)
{
    int i;
    for(i=0;i<n;i++)
       if(old[i]!=now[i]) return 0;
    return 1;
}
int Equal(STREAM data,FLOW FlowData)
{
    if(isEqual(data.SrcMac,FlowData.SrcMac,6))
      if(isEqual(data.DstMac,FlowData.DstMac,6))
        if(isEqual(data.SrcIP,FlowData.SrcIP,4))
          if(isEqual(data.DstIP,FlowData.DstIP,4))
            if(isEqual(data.SrcPort,FlowData.SrcPort,2))
              if(isEqual(data.DstPort,FlowData.DstPort,2))
                if(isEqual(data.VlanID,FlowData.VlanID,2))
                  if(isEqual(data.VlanType,FlowData.VlanType,2))
                    if(data.Protocol==FlowData.Protocol)
                      return 1;
    return 0;
}
long long string2num(uint8 *IP)
{
    long long temp = (long long)IP[3];
    temp += (long long)IP[2] << 8;
    temp += (long long)IP[1] << 16;
    temp += (long long)IP[0] << 24;
     return temp;
}
int add2Hash(STREAM data,FLOW *FlowTable,long long HashNum)
{
     int i,flag=0,cnt=0;
     double temp;
 loop:
     if(cnt++>100000) return 0;
     if(FlowTable[HashNum].flag==0){
           FlowTable[HashNum].flag=1;
           FlowTable[HashNum].timeStart=data.TimeStart+(int)data.MicroSec/1000+(data.MicroSec%1000)/1000.0;
           FlowTable[HashNum].timeEnd=FlowTable[HashNum].timeStart;
           for(i=0;i<6;i++) FlowTable[HashNum].SrcMac[i]=data.SrcMac[i];
           for(i=0;i<6;i++) FlowTable[HashNum].DstMac[i]=data.DstMac[i];
           for(i=0;i<4;i++) FlowTable[HashNum].SrcIP[i]=data.SrcIP[i];
           for(i=0;i<4;i++) FlowTable[HashNum].DstIP[i]=data.DstIP[i];
           for(i=0;i<2;i++) FlowTable[HashNum].SrcPort[i]=data.SrcPort[i];
           for(i=0;i<2;i++) FlowTable[HashNum].DstPort[i]=data.DstPort[i];
           for(i=0;i<2;i++) FlowTable[HashNum].VlanID[i]=data.VlanID[i];
           for(i=0;i<2;i++) FlowTable[HashNum].VlanType[i]=data.VlanType[i];
           FlowTable[HashNum].Protocol=data.Protocol;
           FlowTable[HashNum].FlowBytes=data.FlowBytes;
           FlowTable[HashNum].PacketsNum=1;
           index[FlowCnt++]=HashNum;
           return 1;
     }
     else{
  //???? 
           if(Equal(data,FlowTable[HashNum]))
           {
  //???????flow 
              temp=data.TimeStart+(int)data.MicroSec/1000+(data.MicroSec%1000)/1000.0;
              if (fabs(temp - FlowTable[HashNum].timeEnd)<5 && temp>FlowTable[HashNum].timeEnd){
  //?????????flow 
                 FlowTable[HashNum].timeEnd=temp;
                 FlowTable[HashNum].FlowBytes += data.FlowBytes;
                 FlowTable[HashNum].PacketsNum++;
                 return 1;
              }
              else{
                   /*HashNum=(HashNum*HashNum)%NUM_OF_MAX_FLOW;
                   add2Hash(data,FlowTable,HashNum);//????????flow?*/
                      HashNum = (HashNum + 1) % NUM_OF_MAX_FLOW;
                    while (FlowTable[HashNum].flag == 1){
                      if (Equal(data, FlowTable[HashNum])){
                          temp = data.TimeStart + (int)data.MicroSec / 1000 + (data.MicroSec % 1000) / 1000.0;
                          if (fabs(temp - 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值