4,465
社区成员




void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, eth_len, ip_len, udp_len;
struct sk_buff *skb;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
udp_len = len + sizeof(*udph);
ip_len = eth_len = udp_len + sizeof(*iph);
total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
skb = find_skb(np, total_len, total_len - len);
if (!skb)
return;
skb_copy_to_linear_data(skb, msg, len);
skb->len += len;
skb_push(skb, sizeof(*udph));
skb_reset_transport_header(skb);
udph = udp_hdr(skb);
udph->source = htons(np->local_port);
udph->dest = htons(np->remote_port);
udph->len = htons(udp_len);
udph->check = 0;
udph->check = csum_tcpudp_magic(np->local_ip,
np->remote_ip,
udp_len, IPPROTO_UDP,
csum_partial(udph, udp_len, 0));
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);
iph = ip_hdr(skb);
/* iph->version = 4; iph->ihl = 5; */
put_unaligned(0x45, (unsigned char *)iph);
iph->tos = 0;
put_unaligned(htons(ip_len), &(iph->tot_len));
iph->id = 0;
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;
iph->check = 0;
put_unaligned(np->local_ip, &(iph->saddr));
put_unaligned(np->remote_ip, &(iph->daddr));
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb->protocol = eth->h_proto = htons(ETH_P_IP);
memcpy(eth->h_source, np->dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, np->remote_mac, ETH_ALEN);
skb->dev = np->dev;
netpoll_send_skb(np, skb);
}
kb = alloc_skb(len, GFP_ATOMIC)
//...
//填充IP头,UDP头
dev_queue_xmit(skb);
if (ip_route_output(&rt, dst, 0, 0, dev->ifindex))
skb=alloc_skb(IGMP_SIZE+dev->hard_header_len+15, GFP_ATOMIC);
if (skb == NULL) {
ip_rt_put(rt);
return -1;
}
skb->dst = &rt->u.dst;
//填充ip头,udp头
ip_output(skb);