Installation Guide For PF_RING

本文提供了一个详细的PF_RING安装教程,适用于Ubuntu 9.10系统,包含卸载旧版libpcap、安装依赖软件、使用Subversion获取源代码等步骤,并针对Intel PRO/1000网络卡进行了具体说明。

Installation Guide For PF_RING June 15, 2010

Below you can find an installation guide for PF_RING written by Gunjan Bansal.

 

The original blog entry can be found at this URL .

 

————-

Hi,

This is my first guide so please bear with me for any disrespencies.

 

These steps were tested on Intel Core 2 Duo machine with 4 GB Ram and  Intel(R) PRO/1000 Network Card , with Ubuntu 9.10 installed.This guide explains the installation procedure for Version 4.3.1

 

PF_RING implementation by Luca Deri is a great method for efficient Packet Capture on Commodity Hardware.It can be found on http://www.ntop.org/PF_RING.html

 

 

I made a clean install,no other packages were installed other than mentioned.

 

 

  1. Uninstall libpcap and other dependent applications/library using syanptic or apt-get
  2. Install subversion (For fetching latest source codes),flex and bison (Required to recompile pf_ring aware pcap),ethtool (if not preinstalled,required for some basic Nic info of your computer)
  3. Use Subversion to fetch source codes
    svn co https://svn.ntop.org/svn/ntop/trunk/PF_RING/   PF_RING
  4. Check your current network card/driver using ethtool

    ethtool -i eth0 #change eth0 to your ethernet card Sample
    driver: e1000e
    version: 1.0.2-k2
    firmware-version: 0.4-3
    bus-info: 0000:00:19.0 use man ethtool for more information on how to use ethtool As of version 4.3.1 PF_RING can be fully exploited only on the PF_RING aware device drivers.The modified device drivers for some of the popular network cards can be found in PF_RING/drivers .
    These are modified version of the drivers supplied from respective companies.(Might be a bit older sometimes but will work)
  5. Unload the ethernet card driver (this is shown in the first line of output of above command

    sudo rmmod e1000e
  6. Change current working directory to kernel cd PF_RING/kernel
  7. Make the source codes make Here i had observed that many a times people(even I on first attempt)use sudo make or sudo -s , make . The former is not a correct method and will give you errors such as bounds.c missing , etc.
    Latter is also wrong but will do the job . The reason for such a thing is better explained by the difference in the command “sudo” and “sudo -s” . This can be found at http://ubuntuforums.org/showthread.php?t=983645 , or searching for “difference between sudo and sudo -s” on our favorite google
  8. Now install the newly build source

    sudo make install
  9. Change the working directory to PF_RING/userland/lib cd ../userland/lib
  10. Again build the source codes make
  11. Install the library (This include pfring.h) sudo make install
  12. One bizarre thing that I observed is that the make install copies pfring.h to /usr/local/include but leaves the other dependent files these are :-
    • pfring_e1000e_dna.c
    • pfring_e1000e_dna.h
  13. Although the function in these files are not required in much of the program, they are include in pfring.h and i don’t want to mess up with that.So we copy this to /usr/local/include . Please check this in later versions . cp pfring_e1000e_dna.c /usr/local/include
    cp pfring_e1000e_dna.h /usr/local/include
  14. Now we have to compile PF_RING aware pcap library . Change the working directory to userland/libpcap-1.0.0-ring cd ../libpcap-1.0.0-ring/
  15. Configure ./configure
  16. Build the sources make
  17. Install pf_ring aware libpcap

    sudo make install
  18. Now we need to install the device driver(pf_ring aware).Change the working directory to drivers///src
    In my case it is “drivers/intel/e1000e-1.0.15/src cd ../../drivers/intel/e1000e-1.0.15/src
  19. Build the source

    make
  20. Install the driver sudo make install
  21. Now we need to activate PF_RING if its not already activated . You can use lsmod to check if pf_ring is started or not.Change the working diectory to /lib/modules//kernel/net/pf_ring . cd /lib/modules/2.6.31-14-generic/kernel/net/pf_ring
    Use uname -r to get the kernel version
  22. Enable PF_RING(if already enabled you can disable it using sudo rmmod pf_ring )

    sudo insmod pf_ring.ko transparent_mode=1 More on transparent mode can be found at http://www.ntop.org/blog/?p=56
  23. Now enable to enable your driver go to /lib/modules//kernel/drivers/net/e100e cd /lib/modules/2.6.31-14-generic/kernel/drivers/net/e1000e
  24. Enable the driver sudo insmod e1000e.ko
  25. Now you can start working on your PF_RING application.You will have to recompile many applications such as tcpdump(modified included),network manager etc. Google for doing so :)
基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模型线性化”展开,旨在研究纳米定位系统的预测控制问题,并提供完整的Matlab代码实现。文章结合数据驱动方法与Koopman算子理论,利用递归神经网络(RNN)对非线性系统进行建模与线性化处理,从而提升纳米级定位系统的精度与动态响应性能。该方法通过提取系统隐含动态特征,构建近似线性模型,便于后续模型预测控制(MPC)的设计与优化,适用于高精度自动化控制场景。文中还展示了相关实验验证与仿真结果,证明了该方法的有效性和先进性。; 适合人群:具备一定控制理论基础和Matlab编程能力,从事精密控制、智能制造、自动化或相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能控制设计;②为非线性系统建模与线性化提供一种结合深度学习与现代控制理论的新思路;③帮助读者掌握Koopman算子、RNN建模与模型预测控制的综合应用。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现流程,重点关注数据预处理、RNN结构设计、Koopman观测矩阵构建及MPC控制器集成等关键环节,并可通过更换实际系统数据进行迁移验证,深化对方法泛化能力的理解。
<think>我们有一个Ticket模型,并且已经有一个查询集:Ticket.objects.filter(...).order_by(...).select_related(...) 现在需要关联到Flow模型(假设Flow模型与Ticket通过ticket_id关联,在Django中,通常使用外键关联,假设Flow模型有一个ticket字段,外键到Ticket,关联字段为ticket_id) 需求:对于每个Ticket对象,我们想要获取其对应的每个ticket_status的最后一次出现的时间(即同一个状态有多个节点则取最后一个时间节点) 思路: 1. 我们首先需要关联Flow表。由于一个Ticket可能对应多个Flow记录,我们需要按Ticket分组,然后对每个状态取最后时间。 2. 在Django ORM中,我们可以使用annotate和子查询来实现,但是这里需要每个状态的最后一次时间,而且状态可能有多个,我们希望得到每个状态对应的最后时间,并作为Ticket查询结果的一部分。 然而,由于每个Ticket有多个状态,我们可能需要为每个状态生成一个字段,例如status_A_time, status_B_time等。但状态是动态的,所以这种方法不太灵活。 另一种思路:我们不在Ticket查询集上直接注解每个状态的时间,而是先获取Ticket列表,然后分别查询每个Ticket的Flow记录,按状态分组取每个状态的最大时间(即最后时间)。但这样会导致多次查询数据库,效率不高。 我们可以使用Prefetch对象和prefetch_related来优化,同时自定义查询集。 具体步骤: 1. 首先,我们需要在Ticket查询集上使用prefetch_related来预取相关的Flow记录,并且对于每个Ticket,我们只取每个状态最后一条Flow记录。 但是,prefetch_related默认会取所有相关记录。我们可以通过Prefetch对象来自定义预取查询集。 例如,我们可以这样: from django.db.models import Prefetch, Max, Subquery, OuterRef 但是我们想要每个状态最后一条记录,那么我们可以先为每个状态分组,然后取每个分组中create_time最大的记录。 然而,在预取中无法直接按状态分组然后取每个组最大的一条,因为预取是针对每个Ticket分别执行的,我们可以对每个Ticket的所有Flow记录按状态分组,然后取每个状态的最大时间。但这在数据库层面难以用单个查询实现(除非使用窗口函数,但Django ORM对窗口函数的支持可能有限)。 另一种方法是:我们可以在Flow模型中,为每个ticket和每个状态,找到最大create_time的记录。然后我们可以通过一个子查询来获取每个状态的最后时间,但是这样每个状态都需要一个子查询,如果状态数量固定且不多,可以这样做。但状态通常是动态的,所以不太可行。 考虑性能与实现复杂度,我们可以这样做: 步骤1:先获取Ticket的查询集,并预取相关的Flow记录(全部)。 步骤2:在Python中,对每个Ticket,将其所有Flow记录按状态分组,然后取每组的最大create_time。 但是,这样如果Ticket很多,每个Ticket对应的Flow记录也很多,那么内存和性能可能会有问题。 因此,我们可能需要另一种方法:使用两个查询。 方法: 1. 首先,我们获取所有符合条件的Ticket ID。 2. 然后,我们通过Flow模型,按ticket_id和ticket_status分组,并取每个组的最大create_time。这样我们可以得到一个字典,键为ticket_id,值为另一个字典(状态到时间的映射)。 3. 然后,我们在获取Ticket查询集时,将每个Ticket对象与这个字典关联起来,动态添加属性。 但是,这样需要两个查询,而且第二个查询可能需要处理大量的Flow记录。 考虑到需求是“在已有查询语句基础上”,我们可以尝试在单个查询集中使用annotate,但为每个状态分别注解。如果状态是固定的,比如有5个状态,那么我们可以写5个子查询。 假设我们有状态:1,2,3,4,5 我们可以这样写: Ticket.objects.filter(...).annotate( status1_time=Subquery(Flow.objects.filter(ticket_id=OuterRef('id'), ticket_status=1).order_by('-create_time').values('create_time')[:1]), status2_time=Subquery(Flow.objects.filter(ticket_id=OuterRef('id'), ticket_status=2).order_by('-create_time').values('create_time')[:1]), ... ) 这样,每个状态对应一个字段。但是,如果状态不固定,或者状态很多,这种方法就不合适。 根据引用[2],提到了prefetch_related,我们可以使用Prefetch对象来定制预取,但是预取的是每个Ticket的所有Flow记录,然后我们在Python中处理分组。 具体实现: from django.db.models import Prefetch # 自定义预取的查询集,我们按ticket_id和ticket_status分组,然后取每个组的最大create_time?不行,分组是在数据库层面,我们这里只能按Ticket过滤。 # 实际上,我们无法在预取查询中直接按状态分组取每个组最后一条,所以我们只能预取所有Flow记录,然后在Python中处理。 # 定义预取 flow_queryset = Flow.objects.filter(ticket_id=OuterRef('id')).order_by('ticket_status', '-create_time') # 但是这样还是所有记录,我们无法在预取中分组。 所以,我们只能先预取所有Flow记录,然后在Python中为每个Ticket计算每个状态的最大时间。 代码步骤: tickets = Ticket.objects.filter(ticket_filter).order_by('-id').select_related( 'affiliated_sale__store_name', 'product__name', 'supplier__name', 'installation_site__name', 'installation_site__city__province', 'installation_site__city__name', 'installation_site__district' ).prefetch_related( Prefetch('flow_set', queryset=Flow.objects.order_by('ticket_status', '-create_time')) ) 注意:这里假设Ticket模型中有一个指向Flow的反向关系,名为flow_set(如果没有,则需要根据实际命名,比如如果外键在Flow中,名为ticket,则反向关系默认是flow_set,或者如果设置了related_name,则使用该名称)。 然后,在遍历tickets时,对于每个ticket,我们可以: status_time_map = {} for flow in ticket.flow_set.all(): # 对于每个状态,我们只保留最大的时间,因为我们已经按状态分组并按时间降序,所以每个状态的第一个就是最大的(因为我们按状态排序,然后相同状态内按时间降序) # 但是注意:同一个状态有多条记录,我们按状态分组,然后取每个组的第一条(因为每个状态的第一条就是时间最大的) # 但是同一个状态的多条记录,我们想要的是每个状态的最大时间,所以我们可以: # 方法:创建一个字典,键为状态,值为时间。我们遍历时,如果该状态还没有记录,就添加;如果有,因为我们是按时间降序排的,所以第一个就是最大的,后面同一状态的可以跳过(因为我们按状态排序,相同状态在一起,但是我们只取每个状态的第一个记录即可,但要注意,这样会漏掉其他状态?) # 实际上,我们可以这样: # 按状态分组,然后取每个组的第一条(因为已经按时间降序,所以第一条就是该状态的最大时间) # 但是,我们预取的时候已经按状态排序,然后每个状态内部按时间降序,这样同一个状态的第一条就是该状态的最大时间。 # 但是,同一个状态会有多条记录,我们只需要每个状态的一条记录(最大时间),所以我们可以用一个字典来记录每个状态是否已经出现过。 # 更高效的做法:使用集合记录已经处理过的状态,如果该状态已经处理过,跳过;否则,记录当前flow的状态和时间(因为当前flow是该状态的第一个,也就是时间最大的)。 status_last_times = {} for flow in ticket.flow_set.all(): if flow.ticket_status not in status_last_times: status_last_times[flow.ticket_status] = flow.create_time # 这样,status_last_times就是每个状态的最大时间(最后时间)。 但是注意:预取的queryset是Flow.objects.order_by('ticket_status', '-create_time'),这样相同状态的数据会连续出现,而且每个状态的第一条记录就是该状态的最大时间。 然而,这种方法在遍历每个Ticket的flow_set时,每个Ticket只需要遍历一次,效率相对较高。 但缺点:预取时,每个Ticket的所有Flow记录都会被取出,即使我们只需要每个状态的一条记录。如果Flow记录非常多,可能会影响性能。 另一种优化:我们可以使用聚合查询,但不在主查询中,而是额外做一个查询,获取每个Ticket的每个状态的最大时间。然后映射到Ticket上。 例如: # 先获取ticket_ids ticket_ids = [t.id for t in tickets] # 注意:这里会导致查询数据库,所以我们可以先获取tickets的id列表,然后做第二个查询。 # 然后,查询Flow模型,按ticket_id和ticket_status分组,然后取每个组的最大create_time from django.db.models import Max flow_status = Flow.objects.filter(ticket_id__in=ticket_ids).values('ticket_id', 'ticket_status').annotate(last_time=Max('create_time')) 这样,我们得到一个列表,每个元素是{'ticket_id': id, 'ticket_status': status, 'last_time': time} 然后,我们创建一个字典,以ticket_id为键,值是一个字典(状态->时间) ticket_status_map = {} for item in flow_status: tid = item['ticket_id'] status = item['ticket_status'] time = item['last_time'] if tid not in ticket_status_map: ticket_status_map[tid] = {} ticket_status_map[tid][status] = time 然后,在遍历tickets时,我们可以: for ticket in tickets: status_times = ticket_status_map.get(ticket.id, {}) # 然后就可以使用status_times 这种方法只需要两次查询:第一次查询Ticket,第二次查询聚合数据。 两种方法比较: 方法1(预取所有Flow记录)查询次数少(1次),但数据传输量大(每个Ticket的所有Flow记录)。 方法2(额外聚合查询)需要两次查询,但第二次查询传输的数据量少(只传输每个状态的最大时间,每个Ticket每个状态一条记录)。 根据数据量选择: 如果Flow记录不多,可以用方法1;如果Flow记录很多,方法2更优。 考虑到同一个Ticket的Flow记录可能不会特别多(最多几十条?),我们可以使用方法1。 但用户要求:在已有查询语句基础上,所以我们可以使用prefetch_related来预取Flow记录。 假设Ticket模型关联Flow的反向名称为'flows'(根据实际情况修改),我们可以这样写: tickets = Ticket.objects.filter(ticket_filter).order_by('-id').select_related( 'affiliated_sale__store_name', 'product__name', 'supplier__name', 'installation_site__name', 'installation_site__city__province', 'installation_site__city__name', 'installation_site__district' ).prefetch_related( Prefetch('flows', queryset=Flow.objects.order_by('ticket_status', '-create_time')) ) 注意:如果反向关系名称不是'flows',请设置为实际的名称。 然后,在后续处理每个Ticket时,使用上面提到的方法构建状态时间字典。 示例代码: for ticket in tickets: # 获取这个ticket对应的所有flow记录 flows = ticket.flows.all() status_last_time = {} for flow in flows: # 因为已经按ticket_status升序,create_time降序排列,所以每个状态第一次出现就是最后时间 if flow.ticket_status not in status_last_time: status_last_time[flow.ticket_status] = flow.create_time # 现在status_last_time就是每个状态对应的最后时间 # 可以将其添加到ticket对象上,以便后续使用 ticket.status_last_time = status_last_time 这样,每个ticket对象都有一个status_last_time属性,是一个字典,键是状态,值是最后时间。 注意:如果没有任何Flow记录,则status_last_time为空字典。 如果我们需要在模板中显示,也可以在模板中处理,但最好在视图里处理。 因此,最终的查询语句就是在已有的基础上加上prefetch_related的部分。 另外,关于引用,我们参考了引用[2]中的prefetch_related的使用。 但是,这里要注意,引用[1]中提到了select_related用于外键(一对一或一对多),而prefetch_related用于多对多或一对多(这里是一对多,所以用prefetch_related)。 所以,总结如下: 修改后的查询集: tickets = Ticket.objects.filter(ticket_filter).order_by('-id').select_related( 'affiliated_sale__store_name', 'product__name', 'supplier__name', 'installation_site__name', 'installation_site__city__province', 'installation_site__city__name', 'installation_site__district' ).prefetch_related( Prefetch('flows', queryset=Flow.objects.order_by('ticket_status', '-create_time')) ) 然后,在遍历tickets时,构建字典。 注意:如果Flow模型的反向关系名称不是'flows',请修改为实际的名称。例如,如果外键定义在Flow中,关联到Ticket,且没有设置related_name,那么默认是'ticket_set',那么就是: Prefetch('ticket_set', queryset=Flow.objects.order_by('ticket_status', '-create_time')) 或者,如果设置了related_name,比如: class Flow(models.Model): ticket = models.ForeignKey(Ticket, related_name='flows', ...) 那么就用'flows'。 另外,我们还可以在Prefetch中指定to_attr,这样会将该查询集存储在一个指定的属性中,而不是覆盖默认的manager。例如: Prefetch('flows', queryset=Flow.objects.order_by('ticket_status', '-create_time'), to_attr='ordered_flows') 然后,使用ticket.ordered_flows来获取排序后的列表。 这样,代码更清晰: for ticket in tickets: status_last_time = {} for flow in ticket.ordered_flows: if flow.ticket_status not in status_last_time: status_last_time[flow.ticket_status] = flow.create_time ticket.status_last_time = status_last_time 所以,最终建议代码: # 在查询集上 tickets = Ticket.objects.filter(ticket_filter).order_by('-id').select_related( 'affiliated_sale__store_name', 'product__name', 'supplier__name', 'installation_site__name', 'installation_site__city__province', 'installation_site__city__name', 'installation_site__district' ).prefetch_related( Prefetch('flows', queryset=Flow.objects.order_by('ticket_status', '-create_time'), to_attr='ordered_flows' ) ) # 然后遍历 for ticket in tickets: status_last_time = {} for flow in ticket.ordered_flows: # 按状态取第一个出现的时间(因为排序后,同一状态组内第一个时间最大) if flow.ticket_status not in status_last_time: status_last_time[flow.ticket_status] = flow.create_time ticket.status_last_time = status_last_time 这样,我们就为每个ticket添加了status_last_time属性,它是一个字典,包含每个状态对应的最后时间。 注意:如果实际中Flow模型的反向关系名称不同,请替换'flows'为实际名称。 如果希望更高效,避免在Python中处理分组,也可以考虑使用数据库的聚合功能(如上面提到的第二种方法),但需要两次查询。这里就不详细展开了。 根据用户的需求,我们提供了在已有查询语句基础上添加prefetch_related的方法。 另外,引用[3]和[4]提供了一些filter的用法,但这里没有用到。 所以,最终回答如上。 </think>基于您的需求,需要在现有 Django 查询基础上关联 `flow` 表,并获取工单每个状态的**最后时间节点**。以下是完整解决方案: ### 解决方案步骤 1. **修改查询集添加关联** 使用 `prefetch_related()` 预取 `flow` 表数据,并通过自定义子查询实现按状态分组取最大时间: ```python from django.db.models import Prefetch, Subquery, OuterRef, Max # 子查询:获取每个状态的最大时间 last_flow_subquery = Flow.objects.filter( ticket_id=OuterRef('ticket_id'), ticket_status=OuterRef('ticket_status') ).values('ticket_status').annotate( last_time=Max('create_time') ).values('last_time')[:1] # 预取符合条件的 Flow 记录 flow_prefetch = Prefetch( 'flow_set', # 替换为您的反向关联名 queryset=Flow.objects.annotate( is_last=Subquery(last_flow_subquery, output_field=models.BooleanField()) ).filter(is_last=True), to_attr='last_status_flows' ) # 最终查询集 tickets = Ticket.objects.filter(ticket_filter) .order_by('-id') .select_related( 'affiliated_sale__store_name', 'product__name', 'supplier__name', 'installation_site__name', 'installation_site__city__province', 'installation_site__city__name', 'installation_site__district' ) .prefetch_related(flow_prefetch) # 添加预取 ``` 2. **访问最终时间节点** 遍历结果时,每个 `ticket` 对象的 `last_status_flows` 属性包含各状态最后时间节点: ```python for ticket in tickets: for flow in ticket.last_status_flows: # 预取的最终节点 print(f"状态 {flow.ticket_status}: 最后时间 {flow.create_time}") # 示例输出:状态 3: 最后时间 2023-05-20 14:30:00 ``` ### 关键说明 1. **关联逻辑** - 通过 `Prefetch` 自定义预取,使用子查询过滤出每个状态的最大时间节点(`Max('create_time')`)[^2] - `is_last` 注解字段标记目标记录,避免加载全部流水数据 - `to_attr='last_status_flows'` 将结果存储在新属性中 2. **反向关联名** - `'flow_set'` 需替换为您的实际外键反向名(如未设置 `related_name`,默认为 `小写模型名_set`) - 正确示例:若 `Flow` 模型中外键定义为 `ticket = models.ForeignKey(Ticket, related_name='flows')`,则用 `'flows'` 3. **性能优化** - 单次数据库查询完成所有操作(通过子查询优化) - 避免 N+1 查询问题,尤其当工单量大时效率显著提升[^1][^2] ### 注意事项 - **状态唯一性**:每个状态在 `last_status_flows` 中仅出现一次(取最后时间) - **空值处理**:无 `flow` 记录的工单会返回空列表 - **索引优化**:确保 `flow` 表的 `(ticket_id, ticket_status, create_time)` 有联合索引以加速聚合查询 > 此方案在保留您原有 `select_related` 关联基础上,通过数据库层聚合实现高效的状态时间提取[^2][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值