<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                其實想了很久要不要去分析下key值得提取,因為key值的提取是比較簡單的,而且沒多大實用。因為你不可能去修改key的結構,也不可能去修改key值得提取函數(當然了除非你想重構openVswitch整個項目),更不可能在key提取函數中添加自己的代碼。因此對于分析key值沒有多大的實用性。但我依然去簡單分析key值得提取函數,有兩個原因:第一、key值作為數據結構在openVswitch中是非常重要的,后期的一些流表查詢和匹配都要用到key值;第二、想借機復習下內核網絡協議棧的各層協議信息; 首先來看下各層協議的協議信息: 第一、二層幀頭信息 ~~~ struct ethhdr { unsigned char h_dest[ETH_ALEN]; /*目標Mac地址 6個字節*/ unsigned char h_source[ETH_ALEN]; /*源Mac地址*/ __be16 h_proto; /*包的協議類型 IP包:0x800;ARP包:0x806;IPV6:0x86DD*/ } __attribute__((packed)); /*從skb網絡數據包中獲取到幀頭*/ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) { return (struct ethhdr *)skb_mac_header(skb); } ~~~ 第二、三層網絡層IP頭信息 ~~~ /*IPV4頭結構體*/ struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, // 報文頭部長度 version:4; // 版本IPv4 #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4; #else #error "Please fix <asm/byteorder.h>" #endif __u8 tos; // 服務類型 __be16 tot_len; // 報文總長度 __be16 id; // 標志符 __be16 frag_off; // 片偏移量 __u8 ttl; // 生存時間 __u8 protocol; // 協議類型 TCP:6;UDP:17 __sum16 check; // 報頭校驗和 __be32 saddr; // 源IP地址 __be32 daddr; // 目的IP地址 /*The options start here. */ }; #ifdef __KERNEL__ #include <linux/skbuff.h> /*通過數據包skb獲取到IP頭部結構體指針*/ static inline struct iphdr *ip_hdr(const struct sk_buff *skb) { return (struct iphdr *)skb_network_header(skb); } /*通過數據包skb獲取到二層幀頭結構體指針*/ static inline struct iphdr *ipip_hdr(const struct sk_buff *skb) { return (struct iphdr *)skb_transport_header(skb); } ~~~ 第三、ARP協議頭信息 ~~~ struct arphdr { __be16 ar_hrd; /* format of hardware address硬件類型 */ __be16 ar_pro; /* format of protocol address協議類型 */ unsigned char ar_hln; /* length of hardware address硬件長度 */ unsigned char ar_pln; /* length of protocol address協議長度 */ __be16 ar_op; /* ARP opcode (command)操作,請求:1;應答:2;*/ #if 0 //下面被注釋掉了,使用時要自己定義結構體 /* * Ethernet looks like this : This bit is variable sized however... */ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address源Mac */ unsigned char ar_sip[4]; /* sender IP address源IP */ unsigned char ar_tha[ETH_ALEN]; /* target hardware address目的Mac */ unsigned char ar_tip[4]; /* target IP address 目的IP */ #endif }; ~~~ 對于傳輸層協議信息TCP/UDP協議頭信息比較多,這里就不分析了。下面直接來看key值提取代碼: ~~~ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) { int error; struct ethhdr *eth; //幀頭協議結構指針 memset(key, 0, sizeof(*key));// 初始化key為0 key->phy.priority = skb->priority;//賦值skb數據包的優先級 if (OVS_CB(skb)->tun_key) memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key)); key->phy.in_port = in_port;// 端口成員的設置 key->phy.skb_mark = skb_get_mark(skb);//默認為0 skb_reset_mac_header(skb);//該函數的實現skb->mac_header = skb->data; /* Link layer. We are guaranteed to have at least the 14 byte Ethernet * header in the linear data area. */ eth = eth_hdr(skb); //獲取到以太網幀頭信息 memcpy(key->eth.src, eth->h_source, ETH_ALEN);// 源地址成員賦值 memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);// 目的地址成員賦值 __skb_pull(skb, 2 * ETH_ALEN);//這是移動skb結構中指針 if (vlan_tx_tag_present(skb))// 數據包的類型判斷設置 key->eth.tci = htons(vlan_get_tci(skb)); else if (eth->h_proto == htons(ETH_P_8021Q))// 協議類型設置 if (unlikely(parse_vlan(skb, key))) return -ENOMEM; key->eth.type = parse_ethertype(skb);//包的類型設置,即是IP包還是ARP包 if (unlikely(key->eth.type == htons(0))) return -ENOMEM; skb_reset_network_header(skb);// 函數實現:skb->nh.raw = skb->data; __skb_push(skb, skb->data - skb_mac_header(skb));// 移動skb中的指針 /* Network layer. */ // 判斷是否是邋IP數據包,如果是則設置IP相關字段 if (key->eth.type == htons(ETH_P_IP)) { struct iphdr *nh;//設置IP協議頭信息結構體指針 __be16 offset;// 大端格式short類型變量 error = check_iphdr(skb);// 檢測IP協議頭信息 if (unlikely(error)) { if (error == -EINVAL) { skb->transport_header = skb->network_header; error = 0; } return error; } nh = ip_hdr(skb);// 函數實現:return (struct iphdr *)skb_network_header(skb); // 下面就是IP協議頭的一些字段的賦值 key->ipv4.addr.src = nh->saddr; key->ipv4.addr.dst = nh->daddr; key->ip.proto = nh->protocol; key->ip.tos = nh->tos; key->ip.ttl = nh->ttl; offset = nh->frag_off & htons(IP_OFFSET); if (offset) { key->ip.frag = OVS_FRAG_TYPE_LATER; return 0; } if (nh->frag_off & htons(IP_MF) || skb_shinfo(skb)->gso_type & SKB_GSO_UDP) key->ip.frag = OVS_FRAG_TYPE_FIRST; /* Transport layer. */ if (key->ip.proto == IPPROTO_TCP) { if (tcphdr_ok(skb)) { struct tcphdr *tcp = tcp_hdr(skb); key->ipv4.tp.src = tcp->source; key->ipv4.tp.dst = tcp->dest; } } else if (key->ip.proto == IPPROTO_UDP) { if (udphdr_ok(skb)) { struct udphdr *udp = udp_hdr(skb); key->ipv4.tp.src = udp->source; key->ipv4.tp.dst = udp->dest; } } else if (key->ip.proto == IPPROTO_ICMP) { if (icmphdr_ok(skb)) { struct icmphdr *icmp = icmp_hdr(skb); /* The ICMP type and code fields use the 16-bit * transport port fields, so we need to store * them in 16-bit network byte order. */ key->ipv4.tp.src = htons(icmp->type); key->ipv4.tp.dst = htons(icmp->code); } } // 判斷是否是ARP數據包,設置ARP數據包字段 } else if ((key->eth.type == htons(ETH_P_ARP) || key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) { struct arp_eth_header *arp; // 定義ARP協議頭結構體指針 arp = (struct arp_eth_header *)skb_network_header(skb);// return skb->nh.raw; // 下面就是一些ARP數據包字段的設置 if (arp->ar_hrd == htons(ARPHRD_ETHER) && arp->ar_pro == htons(ETH_P_IP) && arp->ar_hln == ETH_ALEN && arp->ar_pln == 4) { /* We only match on the lower 8 bits of the opcode. */ if (ntohs(arp->ar_op) <= 0xff) key->ip.proto = ntohs(arp->ar_op); memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src)); memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst)); memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN); memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN); } //判斷是否是IPV6數據包,設置IPV6數據包字段 } else if (key->eth.type == htons(ETH_P_IPV6)) { int nh_len; /* IPv6 Header + Extensions */ // IPV6就不分析了 nh_len = parse_ipv6hdr(skb, key); if (unlikely(nh_len < 0)) { if (nh_len == -EINVAL) { skb->transport_header = skb->network_header; error = 0; } else { error = nh_len; } return error; } if (key->ip.frag == OVS_FRAG_TYPE_LATER) return 0; if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) key->ip.frag = OVS_FRAG_TYPE_FIRST; /* Transport layer. */ if (key->ip.proto == NEXTHDR_TCP) { if (tcphdr_ok(skb)) { struct tcphdr *tcp = tcp_hdr(skb); key->ipv6.tp.src = tcp->source; key->ipv6.tp.dst = tcp->dest; } } else if (key->ip.proto == NEXTHDR_UDP) { if (udphdr_ok(skb)) { struct udphdr *udp = udp_hdr(skb); key->ipv6.tp.src = udp->source; key->ipv6.tp.dst = udp->dest; } } else if (key->ip.proto == NEXTHDR_ICMP) { if (icmp6hdr_ok(skb)) { error = parse_icmpv6(skb, key, nh_len); if (error) return error; } } } return 0; } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看