HOWTO: Receive/Send Multicasts Under WinNT/Win95 Using WinSock

本文介绍如何使用 WinSock 在 WinNT 和 Win95 下发送和接收 IP 多播数据报。涵盖设置 TTL 值、指定发送网卡、加入多播组等关键步骤。
HOWTO: Receive/Send Multicasts Under WinNT/Win95 Using WinSock

简单翻译一下:


Sending IP Multicast Datagrams

IP multicasting is currently supported only on AF_INET sockets of type SOCK_DGRAM. 



To send a multicast datagram, specify an IP multicast address with a range of 224.0.0.0 to 239.255.255.255 as the destination address in a sendto() call. 



By default, IP multicast datagrams are sent with a time-to-live (TTL) of 1, which prevents them from being forwarded beyond a single subnetwork. The following code demonstrates how to change this functionality: 





  int ttl = 7 ; // Arbitrary TTL value.



  setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) 

Multicast datagrams with a TTL of 0 are not transmitted on any subnetwork. Multicast datagrams with a TTL of greater than one may be delivered to more than one subnetwork if there are one or more multicast routers attached to the first-hop subnetwork. 



A multicast router does not forward multicast datagrams with destination addresses between 224.0.0.0 and 224.0.0.255, inclusive, regardless of their TTLs. This particular range of addresses is reserved for the use of routing protocols and other low-level topology discovery or maintenance protocols, such as gateway discovery and group membership reporting. Each multicast transmission is sent from a single network interface, even if the host has more than one multicast-capable interface. A socket option is available to override the default for subsequent transmissions from a given socket. For example 



  unsigned long addr = inet_addr("157.57.8.1");

  setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,



            (char *)&addr, sizeof(addr)) 

where "addr" is the local IP address of the desired outgoing interface. An address of INADDR_ANY may be used to revert to the default interface. Note that this address might be different from the one the socket is bound to. 



If a multicast datagram is sent to a group to which the sending host itself belongs (on the outgoing interface), by default, a copy of the datagram is looped back by the IP layer for local delivery. Under some versions of UNIX, there is an option available to disable this behavior (IP_MULTICAST_LOOP). This option is not supported in Windows NT. If you try to disable this behavior, the call fails with the error WSAENOPROTOOPT (Bad protocol option). 



A multicast datagram sent with an initial TTL greater than 1 may be delivered to the sending host on a different interface from that on which it was sent, if the host belongs to the destination group on that other interface. The loopback control option has no effect on such delivery. 

Receiving IP Multicast Datagrams

Before a host can receive IP multicast datagrams, it must become a member of one or more IP multicast groups. A process can ask the host to join a multicast group by using the following socket option 



   struct ip_mreq mreq; 

where "mreq" is the following structure: 



   struct ip_mreq {





       struct in_addr imr_multiaddr;   /* multicast group to join */ 

       struct in_addr imr_interface;   /* interface to join on    */ 





   } 

For example: 



        #define RECV_IP_ADDR   "225.6.7.8"  // arbitrary multicast address



        mreq.imr_multiaddr.s_addr = inet_addr(RECV_IP_ADDR);

        mreq.imr_interface.s_addr = INADDR_ANY;

        err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,

                        (char*)&mreq, sizeof(mreq)) 

Note that it is necessary to bind to an address before calling the setsockopt() function. 



Every membership is associated with a single interface, and it is possible to join the same group on more than one interface. The address of "imr_interface" should be INADDR_ANY to choose the default multicast interface, or one of the host's local addresses to choose a particular (multicast-capable) interface. 



The maximum number of memberships is limited only by memory and what the network card supports. 



The following code sample can be used to drop a membership 



   struct ip_mreq mreq;

   setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,





             (char*)&mreq,sizeof(mreq)) 

where "mreq" contains the same values as used to add the membership. The memberships associated with a socket are also dropped when the socket is closed or the process holding the socket is killed. However, more than one socket may claim a membership in a particular group, and the host remains a member of that group until the last claim is dropped. 



The memberships associated with a socket do not necessarily determine which datagrams are received by that socket. Incoming multicast packets are accepted by the kernel IP layer if any socket has claimed a membership in the destination group of the datagram; however, delivery of a multicast datagram to a particular socket is based on the destination port (or protocol type, for raw sockets), just as with unicast datagrams. To receive multicast datagrams sent to a particular port, it is necessary to bind to that local port, leaving the local address unspecified (that is, INADDR_ANY). 



More than one process may bind to the same SOCK_DGRAM UDP port if the bind() call is preceded by the following code: 



   int one = 1;

   setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) 

In this case, every incoming multicast or broadcast UDP datagram destined for the shared port is delivered to all sockets bound to the port. 



The definitions required for the new, multicast-related socket options are located in the WINSOCK.H file. All IP addresses are passed in network byte-order. 



简单择要中文讲解一下吧:



ip多播目前只有AF_INET/SOCK_DGRAM(数据报)类型socket支持

发送时要指定TTL值,这个值指定了最大能通过的网关或路由器或子网.

int ttl=7;//最多通过7个网关

setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) ;



设定多播发送用的网卡:

unsigned long addr = INADDR_ANY ; //缺省

setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,

            (char *)&addr, sizeof(addr))



然后用标准的sendto发送即是.

注意多播地址集是:[224.0.0.0 to 239.255.255.255]

                 其中[224.0.0.0 to 224.0.0.255]是有特殊用途





多播接收时

1.加入一个多播组:

        struct ip_mreq mreq;//这是个二元组,一个是多播地址,一个是自已的地址

        mreq.imr_multiaddr.s_addr = inet_addr("225.6.7.8");

        mreq.imr_interface.s_addr = INADDR_ANY;//缺省网卡作接收网卡

        err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,

                        (char*)&mreq, sizeof(mreq)) 

2.然后用recv收就是

3.退出一个多播组

    struct ip_mreq mreq;//值和上面是一样的mreq,

   setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,

             (char*)&mreq,sizeof(mreq))



注意:

如果有多于一个进程要绑定于一个udp端口上应在bind之前加一句

int one = 1;

   setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one))
private void generateIPv4FilterLocked(ApfV4GeneratorBase<?> gen) throws IllegalInstructionException { // Here's a basic summary of what the IPv4 filter program does: // // if the network is IPv6 only network: // if the packet is fragmented: // drop // if the packet is a dhcp packet comes from server: // pass // else // drop // if filtering multicast (i.e. multicast lock not held): // if it's DHCP destined to our MAC: // pass // if it's L2 broadcast: // drop // if it's IPv4 multicast: // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mHasClat) { // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addCountAndDropIfR0NotEquals(0xFF11, Counter.DROPPED_IPV4_NON_DHCP4); // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad32Indexed(R0, TCP_UDP_SOURCE_PORT_OFFSET); gen.addCountAndDropIfR0NotEquals(DHCP_SERVER_PORT << 16 | DHCP_CLIENT_PORT, Counter.DROPPED_IPV4_NON_DHCP4); gen.addCountAndPass(Counter.PASSED_IPV4_FROM_DHCPV4_SERVER); return; } if (mMulticastFilter) { final String skipDhcpv4Filter = gen.getUniqueLabel(); // MIUI ADD:NETWORK_BugFixUpstream final String skipIcmpEchoFilter = "skip_icmp_echo_filter"; final String skipNbnsAndDhcpv4Filter = "skip_nbns_and_dhcp_v4_filter"; // END NETWORK_BugFixUpstream // MIUI ADD: WIFI_PowerSave final String dropIcmpUnreachedPort = "dropIcmpUnreachedPort"; final String skipIcmpUnreachedFilter = "skipIcmpUnreachedFilter"; gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); String mifstr = ""; for (Pair<UnreachedPortInfo, ServerSocket> pair: icmpUnreachedPortOccupied) { gen.addJumpIfR0Equals(pair.first.port, dropIcmpUnreachedPort); mifstr += pair.first.toString(); } Log.d(mTAG, "add port:" + mifstr); gen.addJump(skipIcmpUnreachedFilter); gen.defineLabel(dropIcmpUnreachedPort); gen.addCountAndDrop(Counter.DROPPED_ICMP_UNREACHED); gen.defineLabel(skipIcmpUnreachedFilter); // END WIFI_PowerSave // Pass DHCP addressed to us. // Check it's UDP. gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); // MIUI MOD:NETWORK_BugFixUpstream // gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipDhcpv4Filter); gen.addJumpIfR0NotEquals(0xFF11, skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream // Check it's not a fragment or is the initial fragment. // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter); // Check it's DHCP to our MAC address. gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET); // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1ToR0(); // MIUI MOD:NETWORK_BugFixUpstream // gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter); gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream gen.addCountAndPass(Counter.PASSED_DHCP); // Drop all multicasts/broadcasts. // MIUI ADD:NETWORK_BugFixUpstream // Then it'll be checking if it's NBNS packet. // END NETWORK_BugFixUpstream gen.defineLabel(skipDhcpv4Filter); // MIUI ADD: NETWORK_BugFixUpstream // For NBNS Filtering. // Check if it's Nbns packet. gen.addCountAndDropIfR0Equals(NBNS_CLIENT_PORT, Counter.DROPPED_NBNS); // It's not "DHCP to our MAC addr" or "NBNS". Then to Drop all multicasts/broadcasts. gen.defineLabel(skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream // MIUI ADD:NETWORK_BugFixUpstream String isFactoryBuild = SystemProperties.get("ro.boot.factorybuild", "0"); if (!SystemProperties.get(PROPERTY_APF_DROP_IGNORE, "").contains("icmp_echo") && !TextUtils.equals(isFactoryBuild,"1")) { // Check if it's Icmp. gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_ICMP, skipIcmpEchoFilter); // Check if it's Icmp Echo gen.addLoad8(R0, IPV4_TYPE_ICMP_ECHO_OFFSET); gen.addCountAndDropIfR0Equals(ICMP_ECHO, Counter.DROPPED_ICMP_ECHO); gen.defineLabel(skipIcmpEchoFilter); } // END NETWORK_BugFixUpstream // If IPv4 destination address is in multicast range, drop. gen.addLoad8(R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); gen.addCountAndDropIfR0Equals(0xe0, Counter.DROPPED_IPV4_MULTICAST); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). gen.addLoad32(R0, IPV4_DEST_ADDR_OFFSET); gen.addCountAndDropIfR0Equals(IPV4_BROADCAST_ADDRESS, Counter.DROPPED_IPV4_BROADCAST_ADDR); if (mIPv4Address != null && mIPv4PrefixLength < 31) { int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addCountAndDropIfR0Equals(broadcastAddr, Counter.DROPPED_IPV4_BROADCAST_NET); } } // If any TCP keepalive filter matches, drop generateV4KeepaliveFilters(gen); // If any NAT-T keepalive filter matches, drop generateV4NattKeepaliveFilters(gen); // If TCP unicast on port 7, drop generateV4TcpPort7FilterLocked(gen); if (mMulticastFilter) { // Otherwise, this is an IPv4 unicast, pass // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? gen.addLoadImmediate(R0, ETH_DEST_ADDR_OFFSET); gen.addCountAndPassIfBytesAtR0NotEqual(ETHER_BROADCAST, Counter.PASSED_IPV4_UNICAST); gen.addCountAndDrop(Counter.DROPPED_IPV4_L2_BROADCAST); } // Otherwise, pass gen.addCountAndPass(Counter.PASSED_IPV4); } 详细分析一下这段Java代码
06-11
private void generateIPv4FilterLocked(ApfV4GeneratorBase<?> gen) throws IllegalInstructionException { // Here's a basic summary of what the IPv4 filter program does: // // if the network is IPv6 only network: // if the packet is fragmented: // drop // if the packet is a dhcp packet comes from server: // pass // else // drop // if filtering multicast (i.e. multicast lock not held): // if it's DHCP destined to our MAC: // pass // if it's L2 broadcast: // drop // if it's IPv4 multicast: // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mHasClat) { // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addCountAndDropIfR0NotEquals(0xFF11, Counter.DROPPED_IPV4_NON_DHCP4); // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad32Indexed(R0, TCP_UDP_SOURCE_PORT_OFFSET); gen.addCountAndDropIfR0NotEquals(DHCP_SERVER_PORT << 16 | DHCP_CLIENT_PORT, Counter.DROPPED_IPV4_NON_DHCP4); gen.addCountAndPass(Counter.PASSED_IPV4_FROM_DHCPV4_SERVER); return; } if (mMulticastFilter) { final String skipDhcpv4Filter = gen.getUniqueLabel(); // MIUI ADD:NETWORK_BugFixUpstream final String skipIcmpEchoFilter = "skip_icmp_echo_filter"; final String skipNbnsv4Filter = "skip_nbns_v4_filter"; // END NETWORK_BugFixUpstream // MIUI ADD: WIFI_PowerSave final String dropIcmpUnreachedPort = "dropIcmpUnreachedPort"; final String skipIcmpUnreachedFilter = "skipIcmpUnreachedFilter"; gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); String mifstr = ""; for (Pair<UnreachedPortInfo, ServerSocket> pair: icmpUnreachedPortOccupied) { gen.addJumpIfR0Equals(pair.first.port, dropIcmpUnreachedPort); mifstr += pair.first.toString(); } Log.d(mTAG, "add port:" + mifstr); gen.addJump(skipIcmpUnreachedFilter); gen.defineLabel(dropIcmpUnreachedPort); gen.addCountAndDrop(Counter.DROPPED_ICMP_UNREACHED); gen.defineLabel(skipIcmpUnreachedFilter); // END WIFI_PowerSave // Pass DHCP addressed to us. // Check it's UDP. gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addJumpIfR0NotEquals(0xFF11, skipDhcpv4Filter); // Check it's not a fragment or is the initial fragment. // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter); // Check it's DHCP to our MAC address. gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET); // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1ToR0(); gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter); gen.addCountAndPass(Counter.PASSED_DHCP); // Drop all multicasts/broadcasts. // MIUI ADD:NETWORK_BugFixUpstream // Then it'll be checking if it's NBNS packet. // END NETWORK_BugFixUpstream gen.defineLabel(skipDhcpv4Filter); // MIUI ADD: NETWORK_BugFixUpstream // For NBNS Filtering. // Check if it's Nbns packet. gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipNbnsv4Filter); gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); // Check it's addressed to Nbns client port. gen.addCountAndDropIfR0Equals(NBNS_CLIENT_PORT, Counter.DROPPED_NBNS); // It's not "DHCP to our MAC addr" or "NBNS". Then to Drop all multicasts/broadcasts. gen.defineLabel(skipNbnsv4Filter); // END NETWORK_BugFixUpstream // MIUI ADD:NETWORK_BugFixUpstream String isFactoryBuild = SystemProperties.get("ro.boot.factorybuild", "0"); if (!SystemProperties.get(PROPERTY_APF_DROP_IGNORE, "").contains("icmp_echo") && !TextUtils.equals(isFactoryBuild,"1")) { // Check if it's Icmp. gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_ICMP, skipIcmpEchoFilter); // Check if it's Icmp Echo gen.addLoad8(R0, IPV4_TYPE_ICMP_ECHO_OFFSET); gen.addCountAndDropIfR0Equals(ICMP_ECHO, Counter.DROPPED_ICMP_ECHO); gen.defineLabel(skipIcmpEchoFilter); } // END NETWORK_BugFixUpstream // If IPv4 destination address is in multicast range, drop. gen.addLoad8(R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); gen.addCountAndDropIfR0Equals(0xe0, Counter.DROPPED_IPV4_MULTICAST); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). gen.addLoad32(R0, IPV4_DEST_ADDR_OFFSET); gen.addCountAndDropIfR0Equals(IPV4_BROADCAST_ADDRESS, Counter.DROPPED_IPV4_BROADCAST_ADDR); if (mIPv4Address != null && mIPv4PrefixLength < 31) { int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addCountAndDropIfR0Equals(broadcastAddr, Counter.DROPPED_IPV4_BROADCAST_NET); } } // If any TCP keepalive filter matches, drop generateV4KeepaliveFilters(gen); // If any NAT-T keepalive filter matches, drop generateV4NattKeepaliveFilters(gen); // If TCP unicast on port 7, drop generateV4TcpPort7FilterLocked(gen); if (mMulticastFilter) { // Otherwise, this is an IPv4 unicast, pass // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? gen.addLoadImmediate(R0, ETH_DEST_ADDR_OFFSET); gen.addCountAndPassIfBytesAtR0NotEqual(ETHER_BROADCAST, Counter.PASSED_IPV4_UNICAST); gen.addCountAndDrop(Counter.DROPPED_IPV4_L2_BROADCAST); } // Otherwise, pass gen.addCountAndPass(Counter.PASSED_IPV4); }分析这段代码并解决这个问题,基于这种过滤规则,在手机灭屏并且没有插usb的情况下,并且手机处于suspend状态,我们向手机137端口发送nbns包,预想情况下这个包会被过滤掉,但是现在手机收到了包,请分析一下原因并对代码做出修改
06-11
private void generateIPv4FilterLocked(ApfV4GeneratorBase<?> gen) throws IllegalInstructionException { // Here's a basic summary of what the IPv4 filter program does: // // if the network is IPv6 only network: // if the packet is fragmented: // drop // if the packet is a dhcp packet comes from server: // pass // else // drop // if filtering multicast (i.e. multicast lock not held): // if it's DHCP destined to our MAC: // pass // if it's L2 broadcast: // drop // if it's IPv4 multicast: // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mHasClat) { // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addCountAndDropIfR0NotEquals(0xFF11, Counter.DROPPED_IPV4_NON_DHCP4); // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad32Indexed(R0, TCP_UDP_SOURCE_PORT_OFFSET); gen.addCountAndDropIfR0NotEquals(DHCP_SERVER_PORT << 16 | DHCP_CLIENT_PORT, Counter.DROPPED_IPV4_NON_DHCP4); gen.addCountAndPass(Counter.PASSED_IPV4_FROM_DHCPV4_SERVER); return; } if (mMulticastFilter) { final String skipDhcpv4Filter = gen.getUniqueLabel(); // MIUI ADD: WIFI_PowerSave final String dropIcmpUnreachedPort = "dropIcmpUnreachedPort"; final String skipIcmpUnreachedFilter = "skipIcmpUnreachedFilter"; final String skipNbnsv4Filter = "skip_nbns_v4_filter"; final String skipIcmpEchoFilter = "skip_icmp_echo_filter"; final String skipRpcFilter = "skip_rpc_filter"; // miicmpfilter gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); String mifstr = ""; for (Pair<UnreachedPortInfo, ServerSocket> pair: icmpUnreachedPortOccupied) { gen.addJumpIfR0Equals(pair.first.port, dropIcmpUnreachedPort); mifstr += pair.first.toString(); } Log.d(mTAG, "add port:" + mifstr); gen.addJump(skipIcmpUnreachedFilter); gen.defineLabel(dropIcmpUnreachedPort); gen.addCountAndDrop(Counter.DROPPED_ICMP_UNREACHED); gen.defineLabel(skipIcmpUnreachedFilter); // NBNS filter gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipNbnsv4Filter); gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addCountAndDropIfR0Equals(NBNS_CLIENT_PORT, Counter.DROPPED_NBNS); gen.defineLabel(skipNbnsv4Filter); // ping filter String isFactoryBuild = SystemProperties.get("ro.boot.factorybuild", "0"); if (!SystemProperties.get(PROPERTY_APF_DROP_IGNORE, "").contains("icmp_echo") && !TextUtils.equals(isFactoryBuild,"1")) { // Check if it's Icmp. gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_ICMP, skipIcmpEchoFilter); // Check if it's Icmp Echo gen.addLoad8(R0, IPV4_TYPE_ICMP_ECHO_OFFSET); gen.addCountAndDropIfR0Equals(ICMP_ECHO, Counter.DROPPED_ICMP_ECHO); gen.defineLabel(skipIcmpEchoFilter); } int filterEnable = SystemProperties.getInt("persist.miui.wifi.upf.enable", 0); if (filterEnable != 0 && occupyPort(RPC_CLIENT_PORT)) { Log.d(mTAG, "add RPC port:" + RPC_CLIENT_PORT); // RPC filter gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_TCP, skipRpcFilter); gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addCountAndDropIfR0Equals(RPC_CLIENT_PORT, Counter.DROPPED_RPC); gen.defineLabel(skipRpcFilter); } // END WIFI_PowerSave // Pass DHCP addressed to us. // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addJumpIfR0NotEquals(0xFF11, skipDhcpv4Filter); gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipDhcpv4Filter); // Pass DHCP addressed to us. // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addJumpIfR0NotEquals(0xFF11, skipDhcpv4Filter); // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter); // Check it's DHCP to our MAC address. gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET); // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1ToR0(); gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter); gen.addCountAndPass(Counter.PASSED_DHCP); // Drop all multicasts/broadcasts. // MIUI ADD:NETWORK_BugFixUpstream // Then it'll be checking if it's NBNS packet. // END NETWORK_BugFixUpstream gen.defineLabel(skipDhcpv4Filter); // If IPv4 destination address is in multicast range, drop. gen.addLoad8(R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); gen.addCountAndDropIfR0Equals(0xe0, Counter.DROPPED_IPV4_MULTICAST); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). gen.addLoad32(R0, IPV4_DEST_ADDR_OFFSET); gen.addCountAndDropIfR0Equals(IPV4_BROADCAST_ADDRESS, Counter.DROPPED_IPV4_BROADCAST_ADDR); if (mIPv4Address != null && mIPv4PrefixLength < 31) { int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addCountAndDropIfR0Equals(broadcastAddr, Counter.DROPPED_IPV4_BROADCAST_NET); } } // If any TCP keepalive filter matches, drop generateV4KeepaliveFilters(gen); // If any NAT-T keepalive filter matches, drop generateV4NattKeepaliveFilters(gen); // If TCP unicast on port 7, drop generateV4TcpPort7FilterLocked(gen); if (mMulticastFilter) { // Otherwise, this is an IPv4 unicast, pass // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? gen.addLoadImmediate(R0, ETH_DEST_ADDR_OFFSET); gen.addCountAndPassIfBytesAtR0NotEqual(ETHER_BROADCAST, Counter.PASSED_IPV4_UNICAST); gen.addCountAndDrop(Counter.DROPPED_IPV4_L2_BROADCAST); } // Otherwise, pass gen.addCountAndPass(Counter.PASSED_IPV4); }分析一下这段Java代码
06-11
Current state: UP Line protocol state: UP IP packet frame type: Ethernet II, hardware address: 90f7-b2ca-d37b Description: GigabitEthernet4/0/15 Interface Bandwidth: 100000 kbps Loopback is not set Media type is twisted pair Port hardware type is 1000_BASE_T 100Mbps-speed mode, full-duplex mode Link speed type is autonegotiation, link duplex type is autonegotiation Flow-control is not enabled Maximum frame length: 10240 Allow jumbo frames to pass Broadcast max-ratio: 100% Multicast max-ratio: 100% Unicast max-ratio: 100% PVID: 152 MDI type: Automdix Port link-type: Access Tagged VLANs: None Untagged VLANs: 152 Port priority: 0 Last link flapping: 5 weeks 0 days 14 hours 52 minutes Last clearing of counters: Never Current system time:2025-11-11 14:36:51 beijing+08:00:00 Last time when physical state changed to up:2025-10-06 23:45:01 beijing+08:00:00 Last time when physical state changed to down:2025-10-06 23:44:49 beijing+08:00:00 Peak input rate: 45259812 bytes/sec, at 2025-09-25 14:13:49 Peak output rate: 105034047 bytes/sec, at 2025-09-11 08:12:03 Last 300 seconds input: 3506 packets/sec 325268 bytes/sec 3% Last 300 seconds output: 6746 packets/sec 10033736 bytes/sec 81% Input (total): 16272141098 packets, 10286142375543 bytes 16271345463 unicasts, 176989 broadcasts, 618634 multicasts, 0 pauses Input (normal): 16272141086 packets, - bytes 16271345463 unicasts, 176989 broadcasts, 618634 multicasts, 0 pauses Input: 12 input errors, 0 runts, 0 giants, 0 throttles 9 CRC, 0 frame, - overruns, 3 aborts - ignored, - parity errors Output (total): 29871411687 packets, 41653577022415 bytes 29610758010 unicasts, 118316083 broadcasts, 142337594 multicasts, 0 pauses Output (normal): 29871411687 packets, - bytes 29610758010 unicasts, 118316083 broadcasts, 142337594 multicasts, 0 pauses Output: 0 output errors, - underruns, - buffer failures 0 aborts, 0 deferred, 0 collisions, 0 late collisions
11-12
【事件触发一致性】研究多智能体网络如何通过分布式事件驱动控制实现有限时间内的共识(Matlab代码实现)内容概要:本文围绕多智能体网络中的事件触发一致性问题,研究如何通过分布式事件驱动控制实现有限时间内的共识,并提供了相应的Matlab代码实现方案。文中探讨了事件触发机制在降低通信负担、提升系统效率方面的优势,重点分析了多智能体系统在有限时间收敛的一致性控制策略,涉及系统模型构建、触发条件设计、稳定性与收敛性分析等核心技术环节。此外,文档还展示了该技术在航空航天、电力系统、机器人协同、无人机编队等多个前沿领域的潜在应用,体现了其跨学科的研究价值和工程实用性。; 适合人群:具备一定控制理论基础和Matlab编程能力的研究生、科研人员及从事自动化、智能系统、多智能体协同控制等相关领域的工程技术人员。; 使用场景及目标:①用于理解和实现多智能体系统在有限时间内达成一致的分布式控制方法;②为事件触发控制、分布式优化、协同控制等课题提供算法设计与仿真验证的技术参考;③支撑科研项目开发、学术论文复现及工程原型系统搭建; 阅读建议:建议结合文中提供的Matlab代码进行实践操作,重点关注事件触发条件的设计逻辑与系统收敛性证明之间的关系,同时可延伸至其他应用场景进行二次开发与性能优化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值