[완료]커널 영역에서 default gateway 주소 정보 가져오는 방법?

태훈의 이미지

안녕하세요. 드라이버 짜다가 막히는 부분이 생겨서 질문 올립니다.

지금 해야 되는 부분이 리눅스 커널에 있는 default gateway 정보를 가져와야 합니다. 다음과 같은 세가지 방법으로 삽질을 해보았습니다.

1."route"와 같은 user level application code를 보니 "/proc/net/route" 파일을 읽고 쓰는 형식으로 동작하더군요. 똑같은 방식으로 드라이버에서 사용하려고 해도, 커널 영역에서 proc 파일을 읽는 방법을 모르겠습니다.

2. 커널 코드를 뒤져보니 struct rtable 구조체에 rt_gateway 라는 멤버 변수가 있더군요. 이 타입으로 생긴 전역적인 default gateway 변수가 있으면 좋을텐데 못찾았습니다.

3. 커널에 있는 filp_open() 함수를 이용해서 "/proc/net/route" 파일을 열고, filp->f_op->read() 함수를 이용해 보았는데, 파일을 읽지 못하고 EFAULT 값을 리턴합니다. 코드를 대충 훝어보니 user 영역 메모리가 아니면 EFAULT가 리턴 되는것 같더군요.

목적은 커널 영역에서 "route" 와 같은 유틸을 사용해서 설정한 "default gateway address" 정보를 가져와야 합니다.

고수님들의 조언 부탁드립니다.

Hyun의 이미지

Quote:
목적은 커널 영역에서 "route" 와 같은 유틸을 사용해서 설정한 "default gateway address" 정보를 가져와야 합니다.

게이트웨이 주소를 가져오는 목적을 가르쳐주시면 더 수월할지도..
나도 세벌식을 씁니다
태훈의 이미지

게이트웨이 주소를 가져오는 목적에 앞서 현재 작성 중인 드라이버에 대해 알려드려야 겠네요. 리눅스 네트워크 드라이버 입니다.

저희 회사가 네트워크 칩을 판매하는 WIZnet 이라는 회사입니다. 그런데, 저희 회사 제품은 특이하게 칩안에 TCP/IP stack가 들어있습니다. 물론, 기존 네트워크 칩과 동일한 동작도 지원합니다.

그래서, 칩 내부의 TCP/IP stack을 쓰려면 gateway address를 설정해 주어야 합니다. 펌웨어 레벨에서는 칩 레지스터에다가 그냥 바로 쓰면 되는데, 리눅스 드라이버 인지라 리눅스 커널에 설정되어 있는 default gateway address를 읽어서 칩에다가 설정해 주어야 합니다.

소스 코드 뒤지다가 ioctl 쪽에 게이트웨이 주소 추가하는 루틴을 찾았네요. 구현해서 테스트해보고 제대로 동작하면 자답 올려두겠습니다.

ps. TCP/IP stack을 하드웨어로 처리를 하니, 같은 스팩의 네트워크 칩보다 몇배나 뛰어난 성능을 자랑합니다.(bandwidth, cpu 점유율) 혹시나 제품 개발을 하시는데 네트워크 칩이 필요하시면 한번 고려해 보십시오.^^ 물론, 다른 칩보다 좀 비쌉니다.

Just do it!

Hyun의 이미지

칩에있는 네트웍 스택을 사용한다면, 커널의 네트웍 스텍을 사용하지 않는다는 얘기같은데, 커널에서 네트웍 스택을 다른것으로 쓰게 지원해주나요?


나도 세벌식을 씁니다
태훈의 이미지

리눅스 드라이버에서는 별도의 프로토콜을 추가하는 형식으로 처리 하였습니다.

application에서 소켓을 생성할 때 PF_INET이 아닌 다른 프로토콜 패밀리로 소켓을 생성하면 칩 내부에 있는 hardware TCP/IP stack을 사용 할 수 있도록 처리 하였습니다.

리눅스 드라이버 말고, WinCE에서는 일반적인 네트워킹만 드라이버에서 하고 hardware TCP/IP를 쓸려면 별도의 라이브러리를 사용해서 쓰도록 되어있습니다. (라이브러리에서 BSD socket API와 유사한 wizsock API를 제공합니다.)

아직 칩이 나온지 얼마되지 않았고, 쓰시는 분이 많지 않아서 피드백이 부족하기 때문에 어떻게 제공해 드리는게 직관적이고 쉽게 쓸수 있는것인지 모르겠습니다.

관심 있으신것 같아서 드라이버 코드 첨부하였습니다. hardware TCP/IP 처리는 wizsock.* 파일에 구현되어 있습니다.

댓글 첨부 파일: 
첨부파일 크기
Binary Data w5300_driver.tar.gz15.39 KB

Just do it!

Hyun의 이미지

흠... 소켓을 만들 때 파라미터를 다르게 줘야 한다면, 기존 프로그램의 수정이 많아질 수 있을것 같네요. 특히 소스가 없는 컴파일된 오브젝트라던가 대형 네트웍 프로그램이라면 그럴 듯 하네요.
드라이버쪽에서 커널의 네트웍 스택을 삭 바꿔치기 해버리면 소프트웨어의 수정이 없이 감쪽같이 좋은 성능을 낼 수 있을것 같은데...


나도 세벌식을 씁니다
태훈의 이미지

처음에 드라이버 개발할때는 그런 방향으로 했었습니다.
구현 방법은 드라이버 초기화 시점에 sock_unregister() 함수로 BSD socket API와 매핑된 함수들을 내리고, 내가 만든 함수들을 sock_register() 함수로 등록시켜 주는 방식으로 하면 됩니다.

한가지 오해하고 계신 부분이 있는데, W5300은 기존 네트워크 칩과 동일한 동작을 지원합니다. 일반 네트워크 MAC칩과 똑같이 동작도 합니다.
그래서, 기존 프로그램 코드를 변경 없이 그대로 쓰셔도 됩니다. hardware TCP/IP stack과 기존 MAC 동작을 동시에 지원하는 것을 저희 용어로 하이브리드 모드 라고 부릅니다.

다만, 칩 내부에 있는 hardware TCP/IP stack를 이용하려면 현재 드라이버 구조에서는 socket() 함수를 호출 할 때, 다른 인자가 필요하도록 되어있습니다. 이렇게 구현한 이유가 W5300을 이용해서 제품을 개발하시는 고객사에서 high performance를 요구하는 application은 코드 레벨까지 수정이 가능하다는데 착안해서 드라이버 구조를 최대한 심플하게 하기 위해서 였습니다. 드라이버 구현하기 나름인데, 가능하면 최대한 심플하게 가자 라는 취지에서 이렇게 해두었습니다.

결국, application에서 hardware TCP/IP stack 사용 방법에 대한 정책적인 문제가 정확하게 fix 되지 않아서 일단 구현하기 가장 쉬운 형태로 작성해 두었습니다. 말씀하신대로 소프트웨어 변경없이 hardware TCP/IP stack를 사용하려면 proc filesystem을 이용해서 wizconfig 같은 유틸리티를 별도로 만들어서 hardware TCP/IP stack을 사용하는 application을 지정할 수 있게 구현하면 되겠네요. 드라이버가 좀 복잡해 지겠지만, 물량 base가 좀 되는 고객사에서 이런 요청이 들어오면 추후에 이렇게 바뀔수도 있습니다.^^

Just do it!

태훈의 이미지

그리고, hardware TCP/IP stack의 소켓은 최대 8개까지만 생성 할 수 있다는 제한점이 있습니다. 하이브리드 모드로 사용 할 때는 1개 채널을 MAC RAW mode로 써야하기 때문에 최대 7개를 쓸 수 있습니다.

그래서, 소켓이 많이 필요한 application은 그냥 기존의 software TCP/IP stack을 그대로 쓰시고, 네트워크와 MCU에 부하가 많이 걸리는 high performance를 요구하는 application에서만 hardware TCP/IP stack을 쓰시도록 권장해 드리고 있습니다.

Just do it!

jsj3579의 이미지

안녕하세요
커머셜에 관련 된 것이니, 틀린 부분이 있으면 말씀해주세요. 고치겠습니다. :)
w5300칩을 썼었는데, 내부 버퍼가 작아서(잘기억은 안납니다). tcp의 window사이즈가 너무 작았었습니다. 결과적으로 데이터 전송 시간이 오래 걸렸는데요. 이 부분을 어떻게 해결 하셨는지요?

TCP/IP스택이 아무리 빨리 동작한다고 해도, IP통신에는 패킷이 네트워크를 돌아다니는 시간이 대부분이니, 어떻게 해결하셨는지 궁금합니다.

저 좀 살려주세요~~

태훈의 이미지

상황을 보니 예전 W3100 series, W5100을 쓰신것 같네요. 예전 칩들은 8bit 마이컴 시장에서 쓰이던 칩들이라 내부 버퍼 크기가 작습니다.

W5300은 내부에 버퍼가 총 128K가 있어서 이걸 원하시는대로 설정해서 사용하시면 충분히 큰 tcp window size를 쓰실수 있습니다.(일반 TCP 처럼 최대 64K 설정가능)

말씀하신대로, 네트워크 망에 걸리는 overload로 인한 bandwidth는 보장하지 못합니다. 네트워크 망의 bandwidth는 망 사업자의 영역입니다.

저희 칩이 보장하는 부분은 네트워크 칩->application 까지 부분입니다. 그래서, 물리계층에서 같은 bandwidth 로 네트워크 칩에 패킷을 송수신 할 때, 기존에 다른 네트워크 칩보다 몇배나 향상된 성능을 보여 줍니다.

좀 더 많은 지원을 바라시면 저희 홈페이지 Q&A 게시판 에 가셔서 가능하면 자세한 내용을 적어서 글을 남기시면 최대한 지원해 드리도록 하겠습니다.

Just do it!

poplinux의 이미지

좋은 칩이지요.

저희도 적용할 예정입니다.

========================
조직 : E.L.D(Embedded Linux Developer/Designer)
블로그 : poplinux@tistory.com
카페 : cafe.naver.com/poplinux

임베디드 리눅스 관련 프리렌서 지향

태훈의 이미지

감사합니다. 여기에 저희 칩을 아시는분이 계시는군요.^^

Just do it!

태훈의 이미지

const로 선언된 녀석을 후킹해서 찜찜하긴 하지만 게이트웨이 주소를 이런씩으로 가져왔습니다.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/in.h>
#include <linux/net.h>
#include <linux/route.h>
#include <net/inet_common.h>
#include <asm/uaccess.h>
 
/* 기존 ioctl 함수 포인터 */
int (*old_ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg);
 
int my_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
  /* 'route add'를 썼을때 route를 추가하는 커맨드를 가로챔  */
  if( cmd == SIOCADDRT )
  {
     struct rtentry rt;
     struct rtentry *rtp = NULL;
     u32 gwaddr;
     /* user 영역에서 설정할 route 정보를 복사해 온다. */
     if( copy_from_user(&rt, (void __user *)arg, sizeof(rt)) )
       return -EFAULT;
     rtp = &rt;
     /* 구조체에서 실제 Gateway address만 뽑아낸다. */
     gwaddr = ((struct sockaddr_in *)&rtp->rt_gateway)->sin_addr.s_addr;
 
     printk("My Gateway address = %X\n", htonl(gwaddr) );
   }
 
   /* 기존 ioctl 함수 호출 */
   return inet_ioctl(sock, cmd, arg);
 }
 
 
 int test_init(void)
 {
   /* 기존 ioctl 함수 포인터를 저장해둠. */
   old_ioctl = inet_dgram_ops.ioctl;
 
   /* 내가 만든 ioctl 함수로 변경. */
   ((struct proto_ops*)(&inet_dgram_ops))->ioctl = my_ioctl;
   ((struct proto_ops*)(&inet_stream_ops))->ioctl = my_ioctl;
   return 0;
 }
 
 void test_exit(void)
 {
   /* 기존 ioctl 함수로 되돌림. */
   ((struct proto_ops*)(&inet_dgram_ops))->ioctl = old_ioctl;
   ((struct proto_ops*)(&inet_stream_ops))->ioctl = old_ioctl;
 }
 
 module_init(test_init);
 module_exit(test_exit);

Just do it!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.