交换机转发实验一

交换机转发实验一,第1张

交换机转发实验一 采用头文件
# include"include/list.h"

# include 
# include 

# define list_entry(ptr,type,member) \
	(type *)( (char *)ptr - offsetof(type,member))

# define list_for_each_entry(pos,head,member) \
	for( pos = list_entry((head)->next,typeof(*pos),member); \
		&pos->member !=(head);
	   pos = list_entry(pos->member.next,typeof(*pos),member))
           
# define list_for_each_entry_safe(pos,q,head,member) \
	for( pos = list_entry(head->next,typeof(*pos),member),
          q = list_entry(pos->member.next,typeof(*pos),member);
		 &pos->member != head;
		pos = q,
		q = list_entry(pos->member.next,typeof(*q),member)

struct list_head{
    struct list_head *next,*prev;
};

struct listnode{
    struct list_head list;
    int number;
};

static inline void init_list_head(struct list_head *list){
    list->next = list->prev = list;
}

static inline void list_insert(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
{
    next - > prev = new;
    prev -> next = new;
    new -> next = next;
    new -> prev = prev;
}

static inline void list_add_tail(struct list_head *new,struct list_head *head)
{
    list_insert(new,head->prev,head);
}

static inline void list_delete_enrty(struct list_head *entry)
{
	entry->next->prev = entry->prev;
    entry->prev->next = entry->next;
}

void list_example()
{
    struct list_head list;
    init_list_head(&list);
    // 初始化链表,定义一个list_head指针,并且使得list_head的前驱和后继都指向自己
    
    // for 循环构造10个链表项,每一个链表项中的数据从0~9取值。


// 每一个都是:创建链表,分配空间,然后赋数据值,并添加到表尾。


for(int i = 0; i < 10; i++){ struct listnode *node = malloc(sizeof(struct listnode)); node ->number = i; list_add_tail(&node->list,&list); } // 初始化链表完成 fprintf(stdout,"list all numbers : \n"); struct listnode *entry; // list_for_each_entry的成员分别为 // list_for_each_entry(结构体成员,头指针,指针成员(或者结构体成员的部分)) list_for_each_entry(entry,&list,list){ fprintf(stdout,"%d\n",enrty->number); } fprintf(stdout,"list only odd numbers and remove others: \n"); struct listnode *q; list_for_each_entry_safe(entry,q,&list,list){ if(entry->number % 2 == 0){ list_delete_entry(&entry->list); free(entry); } else{ fprintf(stdout,"%d\n",entry->number); } } }

广播网络——广播网络实现 如何构建一个多节点网络?
  • 两个节点互连 Host 1(10.0.0.1/8) ——全双工链路——Host 2(10.0.0.2/8)
  • 多个节点互连 Host 1(10.0.0.1/8)—— Hub ——Host 2(10.0.0.2/8)——Host 3(10.0.0.3/8)
    • 广播网络
广播网络节点(hub)实现
  • 已知网络端口数据结构和发送数据包函数

    // 网络端口数据结构
    typedef struct{
        struct list_head list;
        int fd;
        int index;
        u8 mac[ETH_ALEN]; // 定义以太网接口mac地址长度
        char name[16];
    }iface_info_t;
    
    // 发送数据包函数
    void iface_send_packet(iface_info_t *iface, const char *packet, int len){
        struct sockaddr_11 addr;
        // fill addr...,omitted
        sendto(iface->fd,packet,len,0,&addr,sizeof(addr));
    }
    
    // 节点广播的逻辑
    foreach iface in iface_list:
    	if iface != rx_iface;
    		iface_send_packet(iface, packet,len);
    
  • decive_internal.c

    • 介绍memset库函数

      void *memset(void *str, int c, size_t n)
      str - 指向要填充的内存块
      c - 要被设置的值,该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。


      n - 要被设置为该值的字符数

      • 举一个memset的例子
      # include 
      # include 
      
      int main()
      {
          char str[50];
          
          strcpy(str,"This is string.h library function");
          puts(str);
          
          memstr(str,'$',7);
          puts(str);
          return 0;
      }
      // 效果: This is string.h library function
      // 效果: $$$$$$$ string.h library function
      
# include"headers.h"
# include "base.h"
# include "ether.h"
# include "log.h"

# include 
# include 
ustack_t *instance;
// 注意两个结构体
typedef struct{
    struct list_head iface_list;
    int nifs;
    struct pollfd *fds;
}ustack_t;

typedef struct{
    struct list_head list;
    int fd;
    int index;
    u8 mac[ETH_ALEN];
    char name[16];
} iface_info_t;

 // 查找对应于fd文件描述符的节点,返回指向该节点的指针
iface_info_t *fd_to_iface(int fd)
{
    iface_info_t *iface = NULL;
    /*依然是三个变量的遍历,list_for_each_entry,首先是指向结构体的指针
     然后是头指针,最后是member变量
    所以首先指向结构体的指针iface_info_t *iface,然后是头指针,存储在ustack_t
    里面的 iface_list,也是这个成员类型,然后访问成员,
    在iface_info_t 里面是 list*/
    list_for_each_entry(iface, &instance->iface_list,list){
        if(iface -> fd == fd)
            return fd;
    }
    // 找不到的错误判断
    log(ERROR, "Could not find the desired interface according to fd %d",fd);
    return NULL;
}

// 发送数据包函数
void iface_send_packet(iface_info_t *iface, const char *packet, int len)
{
    struct sockaddr_11 addr;
    memset(&addr,0,sizeof(struct sockaddr_11));
    // 类似于清零 *** 作,把addr中的sizeof(struct sockaddr_11)大小的字节变为0
    // addr填充
    addr.sll_family = AF_PACKET;
    addr.sll_ifindex = iface -> index;
    addr.sll_halen = ETH_ALEN;
    addr.sll_protocol = htons(ETH_P_ARP);
    struct ether_header *eh = (struct ether_header *)packet;
    memcpy(addr.slll_addr,eh->ether_dhost,ETH_ALEN);
    
    if(sendto(iface->id,packet,len,0,(const struct sockaddr *)&addr,
             sizeof(struct sockaddr_11)) < 0){
        perror("Send raw packet failed");
    }
}

int open_device(const char *dname)
{
    int sd = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
    if(sd < 0){
        perror("creating SOCK_RAW failed!");
        return -1;
    }
    
    struct ifreq ifr;
    bzero(&ifr,sizeof(struct ifreq));
    // 置零 *** 作
    strcpy(ifr.ifr_name,dname);
    if(ioctl(sd,SIOCGIFINDEX,&ifr)< 0){
        perror("ioctl() SIOCGIFINDEX failed!");
        return -1;
    }
    
    struct sockaddr_11 sll;
    bzero(&sll,sizeof(sll));
    sll.sll_family = AF_PACKET;
    sll.sll_ifindex = ifr.ifr_index;
    
    if(bind((int)sd, (struct sockaddr *)&sll,sizeof(sll)) < 0){
        perror("binding to device failed!");
        return -1;
    }
    
    if(ioctl(sd,SIOCGIFHWADDR,&ifr) < 0){
        perror("Start(): SIOCGIFHWADDR failed!");
        return -1;
    }
    // We could still capture all the packets even if not in promisc mode.
 # if 0
    struct packet_mreq mr;
    bzero(&mr,sizeof(mr));
    mr.mr_ifindex = sll.sll_ifindex;
    mr.mr_type = PACKET_MR_PROMISC;
    
    if(setsockopt(sd,SOL_PACKET, PACKET_ADD_MEMBERSHIP,&mr,sizeof(mr)) < 0){
        perror("Start():setsockopt() PACKET_ADD_MEMBERSHIP failed!");
        return -1;
    }
 # endif
    return sd;
}

int read_iface_info(iface_info_t *iface)
{
    int fd = open_device(iface->name);
    iface->fd = fd;
    int s = socket(AF_INET,SOCK_DGRAM,0);
    struct ifreq ifr;
    strcpy(ifr.ifr_name, iface->name);
    
    ioctl(s,SIOCGIFINDEX,&ifr);
    memcpy(&iface->mac,ifr.ifr_hwaddr.sa_data,sizeof(iface->mac));
    
    // As a broadcast(hub),its interfaces have no IP address.
# if 0
    struct in_addr ip,mask;
    // get ip address
    if(ioctl(fd,SIOCGIFADDR,*ifr) < 0){
        perror("Get IP address failed");
        exit(1);
    }
    ip = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
    iface->ip = ntol(*(u32 *)&ip);
    strcpy(iface->ip_str,inet_ntoa(ip));
 	// get net mask
    if(ioctl(fd,SIOCGIFNETMASK,&ifr) < 0){
        perror("Get IP mask failed");
        exit(1);
    }
    mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
    iface->mask = ntol(*(u32*)&mask);
#endif
    return fd;
}

static void find_available_ifaces()
{
    init_list_head(&instance->iface_list);
    
    struct ifaddrs *addrs,*addr;
    getifaddrs(&addrs);
    for(addr = addrs;addr !=NULL;addr = addr->ifa_next){
        if(addr->ifa_addr && addr->ifa_addr->sa_family==AF_PACKET && \
          strstr(addr->ifa_name,"-eth")!=NULL){
            iface_info_t *iface = malloc(sizeof(iface_info_t));
            bzero(iface,sizeof(iface_info_t));
            
            init_list_head(&iface->list);
            strcpy(iface->name,addr->ifa_name);
            list_add_tail(&iface->list,&instance->iface_list);
            instance->nifs +=1;
        }
    }
    freeifaddrs(addrs);
    
    if(instace->nifs == 0){
        log(ERROR,"could not find available interfaces.");
        exit(1);
    }
    char dev_names[1024]="";
    iface_info_t *iface = NULL;
    list_for_each_entry(iface,&instance->iface_list,list){
        sprintf(dev_names + strlen(dev_names),"%s",iface->name);
    }
    log(DEBUG,"find the following interfaces:%s.",dev_names);
}

void init_all_ifaces()
{
    find_available_ifaces();
    
    instance-> fds = malloc(sizeof(struct pollfd)*instance->nifs);
    bzero(instance->fds,sizeof(struct pollfd)*instance->nifs);
    
    iface_info_t *iface = NULL;
    int i = 0;
    list_for_each_entry(iface,&instance->iface_list,list){
        int fd = read_iface_info(iface);
        instance->fds[i].fd=fd;
        instance ->fds[i].events = POLLIN;
        
        i+=1;
    }
}

void init_ustack()
{
    instance = malloc(sizeof(ustack_t));
    bzero(instance,sizeof(ustack_t));
    init_list_head(&instance->iface_list);
    init_all_ifaces();
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/578574.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存