컴퓨터공부

socket 및 socket buffer

achivenKakao 2006. 8. 14. 05:05

Socket socket buffer

 

Socket이란 API로서 TCP/IP로의 연결통로를 제공한다고 생각하면 된다. , socket을 통해서 application data network을 통해서 목적지로 전송할 수 있다. 이것은 주로 library로 제공되며, program compile하게 될 때 link된다. 여기서는 socket programming에 대한 것은 생략하도록 했다. 이것은 너무나 많은 책들에서 다루고 있기에 그것들을 참고하기 바란다.

 

Socket에서 사용하는 data들은 socket buffer라는 형태로 만들어져서 linux에서 제공하는 protocol stack의 처리를 받게 되며, 최종적으로 network device driver에 도달하게 된다. 따라서, network device driver writer socket buffer에 대한 것만 생각하면 된다. 나중에 data을 상위의 protocol stack으로 전송하게 될 때도 사용하게 되는 것이 바로 이러한 socket buffer이다.

 

먼저 socket buffer에 대한 field중 다음과 같은 것에 대해서 알아보자.

 

l         struct device *dev – socket buffer가 전달되거나 보내진 device를 가르킨다.

l         __u32 saddr, __u32 daddr, __u32 raddr – IP protocol에 의해서 사용되며, source, destination, router의 주소를 가르킨다.

l         unsigned char *head,  unsigned char *data, unsigned char *tail, unsigned char *end – network을 통해서 전달되는 packet data를 가르키는 부분이다.

l         unsigned long len – data 자체의 길이를 나타내는 것으로 skb->tail – skb->head를 가진다.

l         unsigned char ip_summed – TCP/IP에 의해서 checksum을 하는데 사용된다. 이것은 receive packet에 대해서 device driver에 의해서 set된다.

l         unsigned char pkt_type – PACKET_HOST, PACKET_BROADCAST, PACKET_MULTICAST, 혹은 PACKET_OTHERHOST등의 값으로 driver에 의해서 set된다. , 받은 packet host로 오는 것인지, broadcast된 것인지, 혹은 multicast 된 것인지를 나타낸다. 하지만, ethernet driver의 경우에는 eth_type_trans가 이 역할을 해주므로 따로 나타내어줄 필요는 없다.

l         Union { unsigned char *raw; […] } mac – packet receive할 때 set되며 packet을 처리하는데 사용된다. 위에서 언급한 것과 마찬가지로 eth_type_trans가 처리를 해주므로 ethernet에서는 다룰 필요가 없다.

 

이것 이외에도 여러 개의 field socket buffer에 있지만 관심을 가질 필요는 없다. 이것은 우리가 다루어 주지 않아도 상관없다.

 

Socket buffer에서 사용하게 되는 function으로는 다음과 같은 것이 있다.

 

l         struct sk_buff *alloc_skb( unsigned int len, int priority ); - socket buffer를 할당한다.

l         struct sk_buff *dev_alloc_skb( unsigned int len ); - socket bufer를 할당하며, priority GFP_ATOMIC을 주고, head tail사이에 16bytes를 남겨둔다.

l         void kfree_skb( struct sk_buff *skb, int rw ); - 할당된 socket buffer free한다.

l         void dev_kfree_skb( struct sk_buff *skb, int rw ); - 할당된 socket buffer free하며, buffer locking을 정확히 처리한다. Driver에서는 dev_kfree_skb()를 사용해서 socket buffer free해주어야 한다.

l         unsigned char *skb_put( struct sk_buff *skb, int len ); - buffer의 끝에 data를 넣고, tail len field를 고친다.

l         unsigned char *skb_push( struct sk_buff *skb, int len ); - socket buffer의 앞에서부터 data를 채워넣는다.

l         int skb_tailroom( struct sk_buff *skb ); - socket buffer에 남은 data를 위한 space의 크기를 return한다.

l         int skb_headroom( struct sk_buff *skb ); - data앞에 남은 부분의 사용 가능한 space의 크기를 return한다.

l         void skb_reserve( struct sk_buff *skb, int len ); - socket buffer에 데이터를 쓰기 전에 headroom space를 마련한다.

l         unsigned char * skb_pull( struct sk_buff *skb, int len ); - packet head로부터 data를 떼어낸다.

 

위와 같은 함수들을 사용해서 kernel로부터 넘겨받은 socket buffer에 대한 연산을 하며, 또한 받은 packet에 대해서 kernel로 넘겨주기 전에 socket buffer의 형태로 만들어 준다. , kernel에서는 보내고자 하는 data socket buffer의 형태로 만들어주며, 넘겨 받는 것은 socket buffer라는 것을 가정할 수 있게 된다.[1][그림] socket buffer가 어떻게 구현되어 있는지를 보여주고 있다.

그림 Socket Buffer Structure

[그림]에서 보듯이 socket buffer head tail data를 삽입할 수 있기에, packet header를 붙이거나 tail CRC(Cycle Redundancy Check)[2]와 같은 checksum을 붙이게 될 때 사용하기 편리하다. 참고로 이것은 SCO UNIX의 경우 stream driver를 구현하는 것과 유사하다.



[1] SCO unix에서의 network driver stream이라는 것으로 이와 같은 일을 해주고 있다.

[2] CRC packet data 정확한 지를 점검하기 위한 목적으로 전달되며, 주로 polynomial 나눈 나머지 값을 setting한다.

 

http://www.comembedded.wo.to