taoqian's profiledifferent life, differen...PhotosBlogListsMore Tools Help

Blog


    July 19

    一不小心闯入了多播

    以前没有接触过Mcast,常常有畏惧心理。
    这段时间有所接触,发现也不过如此。
     
    我们分为两部分kernel, protocol.
    在kernel中维持了一个(S,G,iff,off)的大数组。其中,S,源地址,G,组地址,iff,进口接口,用作RPF检查,off是出口list,是ip packet的出口。
    刚开始的时候,这个大树组是空的,这个大数组是protocol(如dvmrp,pim)建立的,是data driven.
    kernel中来了一个数据包,在(S,G,iff,off)中找不到,就向protocol发一个NO CACHE的event,这里面含有(S,G)
     
    然后protocol怎么处理呢?
     
    这还需要补充一点protocol怎么建立routing的。
    我们知道在单播中可以通过RIP, OSPF建立路由表(dest ip,
    nexthop,nexthop if)
    dvmrp也建立自己的路由表,不过dest ip是src ip, nexthop也变成了到源地址的上游router.
     
    protocol收到NO CACHE的event之后,根据(S,G)中的S在protocol建立的路由表中寻找,可以找到iff,off,然后这些信息被写到kernel进去。可以认为在protocol中有与kernel中对应的结构(S,G,iff,off)
     
     
    影响这个结构的还有prune,graft等事件。
    还有igmp的report,都会影响(S,G,iff,off),进而影响到kernel中的对应结构。
     
     
    事实上,kernel中的IPMC代码很少,但是protocol代码是复杂的,工作基本上都是上面的protocol完成的。
     
     
     
    July 07

    我所用过的和看到过的socket

    这一两周写也一种socket,看到了另外两种socket.
    以前脑海中有些模糊的东西渐渐得到澄清,另外,也很佩服Unix socket之强大,封装了如此多的通信方式.
    详细的可以参展linux下的man socket, man 7 unix, man 7 ip, man 7 socket.
    另外当然可以看看Richard Stevens的那本IPC communication第一卷.
     
    1.raw socket,
     domain 是AF_PACKET或者是PF_PACKET可以看看7月7日的如何从某个网口收取所有的packet  这篇文章,实际上讲的如何访问network driver(2层)的东西,进行包过滤,根本不经过TCP/IP stack要提供的是net device 的ifindex参数。
     
    2
    ip socket,这是我们的书中经常讲的,可以让两台host上的两队ip src/tcp or udp port进行远程通信,另外在可以在用户程序中跑一个process来监听内核中来的某种协议的包。(如IGMP,ICMP....)
    对于后者
    igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
    然后select,
    就可以收到从kernel发上来的igmp packet了。
     
     
    3 Unix socket.
    AF_LOCAL,或者AF_UNIX.
    一般来讲,这是用在同一台host上的IPC.
     
    我以前看XWindows,发现X server与X Client之间用socket进行通信,很是奇怪,这跟我以前理解的socket(就是IP socket)根本不是一回事情.这实际上
    char path[]="/tmp/socketfile";
    sockaddr_un addr;
    sock =socket (AF_UNIX, SOCK_STREAM, 0);
        /* Unlink. */
    unlink (path);
      /* Prepare accept socket. */
    memset (&addr, 0, sizeof (struct pal_sockaddr_un));
    addr.sun_family = AF_UNIX;
    memcpy(add,sun_path,path,sizeof(path));
    addr.sun_len = len =sizeof(path);
    bind (sock,  &addr, len);
     
    ....之后就可以进行通信了
    这样server/client就可以过一个文件连接起来,做到IPC.
    据说这样的效率比较高,IMI与IMI shell就是这样通信的。
     
     
    我们在谈论Socket的时候一定要搞清楚是那种socket,因为socket包含范围实在太广了,它实际上是各种通信方式的一种封装。
     
     

    如何从某个网口收取所有的packet

    记住要打开混杂模式,才能受到所有的包.
    #include <string.h>
    #include <sys/socket.h>
    #include <netpacket/packet.h>
    #include <net/ethernet.h>
    #include <sys/ioctl.h>
    #include <net/if.h>
    #include <sys/select.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <netinet/in.h>
    main()
    {
     int32 sock,sock_selected,len;
     uint8 buffer[1500]={0}
     int32 maxfdp = 0;
     struct sockaddr_ll me;
     struct ifreq  ifr;
     fd_set fds;
     sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
     if (sock < 0)
            {
                printf("create socket error\n");
                return -1;
            }
     maxfdp = sock;
     memset(&ifr, 0, sizeof(struct ifreq));
            strcpy(ifr.ifr_name, "eth0");
            if (ioctl(sock[i], SIOCGIFINDEX, &ifr, sizeof(struct ifreq)) < 0)
            {
                printf("socket ioctl error\n");
                return -1;
            }

     memset(&me, 0, sizeof(struct sockaddr_ll));
            me.sll_family = AF_PACKET;
            me.sll_ifindex = ifr.ifr_ifindex;
            me.sll_pkttype = PACKET_OTHERHOST;
            if (bind(sock, (struct sockaddr *)&me, sizeof(struct sockaddr_ll))<0)
            {
                printf("socket error in bind\n");
                return -1;
            }
     
     maxfdp = maxfdp + 1;
     for(;;)
     {
      FD_ZERO(&fds);       
                 FD_SET(sock,&fds);
       
      sock_selected=select(maxfdp,&fds,NULL,NULL,0);
         
     } 
     switch(sock_selected)
            {
                case -1:
                    printf("Error in selecting socket!\n");
                    return -1;
                    break;
               
                case 0:
                    break;
                   
                default:
                
                        if(FD_ISSET(sock[i],&fds)) 
                        {
                            len = recvfrom(sock, buffer, 1500, 0, 0, 0);
                            if (len < 0)
                            {
                                printf("Receive socket error\n");
                                continue;
                            }
                        }
             }
     
    }
    July 05

    重读TCP/IP 详解卷一之读书笔记

    第一章:概述
    讲述了分层的概念,解释了链接层/网络层/传输层/应用层,这里都是描述性的解释,并不精确。总之我们明白网络层负责routing,传输层为应用程序提供可靠的端对端的传输。网络层其实是不可靠的,传输层是可靠的(TCP)。
     
    这些只对TCP/IP这个具体的协议占有效,其实IP over ATM, ethernet over MPLS.....,上层可以是不可靠的,下层可以是可靠的。。。。
     
    有两个RFC值得一看:主机需求RFC1122,1123
    路由器需求,RFC1009
     
    第二章:链路层
    以太网封装是在RFC894提出来的
    IEEE802封装是后来在RFC1042提出来的,两种格式并不一样。
    以太网是一个无连接,无确认的链路层,报头中部给出长度,长度实际是硬件给出的。
    IEEE802中包含了一个LLC,这实际上可以提供一个由连接,有确认的数据链路层,而且报头上含有长度,所以可以由软件来实现连接。
    如果length/type>1500,我们可以认为是以太网。
    length/type<1500,可以认为是IEEE802.
     
    本章中还提出了PPP这种链路层,讲述了如何构造一个数据链路层,譬如有CRC纠错,payload类型。。。
     
    loopback接口,在unix机器上,loopback接口和以太网接口是并列的,这是因为数据在到达loopback之前经过了所有的传输层和网络层。
     
    IP数据在送到链路层的时候,会判断包长是否超过interface的MTU,如果是就
    分片。
    两台通信主机路径上最小的MTU被称为路径MTU,RFC1191讲述了如何发现路径MTU.
     
    SLIP协议中对于交互分组数据优先进入队列,并用响应时间订出了MTU.
    以太网的MTU应该跟载波监听有关。
     
    第三章:IP
    在本章刚开始,定义了unreliable和connectless,unreliable表示包可能中途会丢掉,connectless表示每个数据包独立处理,可以不按顺序发送。
    IP就是一个unreliable,connectless的协议。
     
    IP包头长度从20到64个字节不等!!!
    其中包含IPDA,IPSA,TTL(生存时间),TOS(优先级),payload类型(protocol),与分片有关的信息。
    在交换机\路由器中可能对二层(cos),三层(TOS)乃至四层的信息进行分析,从而确定排队顺序。
    所以我们不能说路由器是一个简单的三层设备。
     
    IP routing分析IPDA,确定nexthop,nexthop是一台路由器或者主机。
    当然,nexthop还暗含了一个网络接口。
     
    这章还讲了子网,我搞不清楚这样讲有什么意义,既然有了CIDR,子网还有什么意思呢?
     
    July 02

    积极向上的东西

    来到新的境有了一段时间,感受到以前没有感受过的东西.
    1:team work.在我们这个领域里,东西如此之多,关系如此复杂,一个人其实很难掌握的到,得到一个task,自己去drive,自己去领导,去沟通,只要事情能够成功,就应该有些“不择手段”,不应该将触角伸向所有的地方。
     
    2:欣赏别人.在任何team里,攻击别人都是非常不对的,要学会说好话,嘴巴甜一些,原则上讲,虚伪的好话好过所谓的忠言逆耳。不过,话又说回来,这需要上下沟通,制度性的沟通。领导信任员工是员工最大的动力,不要去批评,批评解决不了什么问题,出了问题要solution.
     
    3:兴趣是最好的老师:一个team里当然有大致的分工,不过不应该太严格,不同的人性格不一样,有的人专一安静,有的人性急好动(me?),但是公司这两种人公司都需要,性急不是错,性急是成就事业的保障。team应该在分配task的时候给员工自由选择的机会,这非常重要。任何人都有他的独特价值,不要往一个model里套。