TCP 송수신 관련하여 질문이 있습니다.
안녕하세요.
이번에 리눅스 커널을 처음 만저보는 초보입니다.
이번 프로젝트에서 TCP 헤더 아래에 제가 만드는 헤더를 빌드하여 사용하고 싶습니다.
이를 위하여 struct sk_buff(include/linux/skbuff.h)에 저희가 사용할 헤더를 지정하는 변수를 정의했습니다.
struct sk_buff { /* These two members must be first. */ struct sk_buff *next; ........ ........ sk_buff_data_t d3_header; // 제가 정의한 헤더의 위치입니다. sk_buff_data_t transport_header; sk_buff_data_t network_header; ....... ....... };
그 아래 TCP 헤더를 삽입하는것 처럼 저도 같은 방식으로 저의 헤더를 삽입하는 곳을 만들었습니다.
#ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_d3_header(const struct sk_buff *skb) { return skb->head + skb->d3_header; } static inline void skb_reset_d3_header(struct sk_buff *skb) { skb->d3_header = skb->data - skb->head; } static inline void skb_set_d3_header(struct sk_buff *skb, const int offset) { skb_reset_d3_header(skb); skb->d3_header += offset; } ........ #else /* NET_SKBUFF_DATA_USES_OFFSET */ static inline unsigned char *skb_d3_header(const struct sk_buff *skb) { return skb->d3_header; } static inline void skb_reset_d3_header(struct sk_buff *skb) { skb->d3_header = skb->data; } static inline void skb_set_d3_header(struct sk_buff *skb, const int offset) { skb->d3_header = skb->data + offset; }
마지막으로 데이터를 전송하는 tcp_transmit_skb() 함수에서 TCP 헤더와 마찬가지로 저희가 원하는 헤더를 빌드할 수 있었습니다.
문제는 Packet을 보내면 Sender에서는 MSS*4 만큼을 한꺼번에 보내면, Receiver측에서는 이를 분할해서 받는겁니다. (가령 MSS=1448이라고 하면, Sender가 저희가 만든 헤더를 포함하여 2896Byte를 보내면 Seq는 Seq+2896으로 설정되지만, Receiver는 처음에는 1448Byte만 받고 Seq는 Seq+1448로 설정 되고 다음번 나머지 데이터를 받으며 Seq+2996으로 설정됩니다. 이 때 두 번째 Packet에는 제가 만든 헤더가 포함되어 있지 않습니다.)
이는 Sequence Number로 확인할 수 있었으며, 이를 찍어본 곳은 Receiver의 tcp_v4_rcv() (net/ipv4/tcp_ipv4.c)이고, Sender측은 tcp_transmit_skb() (net/ipv4/tcp_output.c)입니다.
이렇게 MSS만큼으로 TCP를 분할하여 보내는곳(혹은 받는곳)이 어디인지 궁굼합니다. Packet을 받을 때 저희 해더를 갖고 있다지 않가 복사를 하기 위해 위치를 참조할 때 커널패닉이 발생합니다.
분할되는 지점을 알면 복사를 하던, 분할된 Packet인지 알고 무시하던 할 수 있으므로 그 부분만 찾으면 될 듯 합니다.
고수님들의 가르침을 받고 싶습니다.
새해 복 많이 받으세요.
댓글 달기