calls dev-> hard_start_xmit ()
calls spin_unlock_bh () звільняємо девайс
DEVICE-> hard_start_xmit () - залежить від девайса, drivers/net/DEVICE.c
в Загалом перевіряє чи відкрито пристрій
посилає заголовок
говорить системної шині послати пакет
оновлює статус
inet_sendmsg () - net/ipv4/af_inet.c
int inet_sendmsg (struct socket * Sock, struct msghdr * msg, int size,
struct scm_cookie * scm)
{
struct sock * sk = sock-> sk;
/* Біндо сокет. */p> if (sk-> num == 0 && inet_autobind (sk)! = 0)
return -EAGAIN;
викликаємо функцію протоколу щоб послати дані
return sk-> prot-> sendmsg (sk, msg, size);
}
ip_build_xmit - net/ipv4/ip_output.c (604)
calls sock_alloc_send_skb () виділяємо пам'ять
= заголовочек =
if (! sk-> protinfo.af_inet.hdrincl) {p> iph-> version = 4;
iph-> ihl = 5;
iph-> tos = sk-> protinfo.af_inet.tos;
iph-> tot_len = htons (length);
iph-> frag_off = df;
iph-> ttl = sk-> protinfo.af_inet.mc_ttl;
ip_select_ident (iph, & Rt-> u.dst, sk);
if (rt-> rt_type! = RTN_MULTICAST)
iph-> ttl = sk-> protinfo.af_inet.ttl;
iph-> protocol = sk-> protocol;
iph-> saddr = rt-> rt_src;
iph-> daddr = rt-> rt_dst;
iph-> check = 0;
iph-> check = ip_fast_csum ((unsigned char *) iph, iph-> ihl);
err = getfrag (frag, ((char *) Iph) + iph-> ihl * 4,0, length-iph-> ihl * 4);
}
calls getfrag () копіюємо дані у користувача
returns rt-> u.dst.output () [= dev_queue_xmit ()]
ip_queue_xmit () - net/ipv4/ip_output.c (234)
cмотри маршрут
добудовуємо ip заголовок
фрагментірум якщо треба
adds IP checksum
calls skb-> dst-> output () [= dev_queue_xmit ()]
qdisc_restart () - net/sched/sch_generic.c (50)
вириваєм пакет з черги
calls dev-> hard_start_xmit ()
оновлюємо статистику
if якщо помилка знову стввім пакет у чергу
sock_sendmsg () - net/socket.c (325)
перевіряємо права і все таке
calls scm_sendmsg () [socket control message]
шлемс дані
calls sock-> ops [inet] -> sendmsg () and destroys scm
>>> sock_write () - net/socket.c (399)
calls socki_lookup () accоцііруем сокет з inode
заповнюємо заголовок повідомлення
returns sock_sendmsg ()
tcp_sendmsg () - net/ipv4/tcp.c (755)
ждемс з'єднання
skb = tcp_alloc_pskb пам'ять
calls csum_and_copy_from_user () робимо checksum & копіюємо
calls tcp_send_skb ()
tcp_send_skb () - net/ipv4/tcp_output.c (160)
це головна routine посилки буфера
ми ставимо буфер в чергу і вирішуємо залишити його там або послати
calls __skb_queue_tail () додаємо в чергу
...