⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev_nm_16esw.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 5 页
字号:
      }      p->egress_bitmap = 1 << egress_port;      p->egress_ut_bitmap = p->vlan_entry[2] &          BCM5600_VTABLE_UT_PORT_BMAP_MASK;   } else {      /* Multicast: send the packet to the egress ports found in MARL table */      p->egress_bitmap = arl_entry[2] & BCM5600_MARL_PORT_BMAP_MASK;      p->egress_ut_bitmap = arl_entry[3] & BCM5600_MARL_UT_PORT_BMAP_MASK;   }#if DEBUG_FORWARD   {      char buffer[1024];      BCM_LOG(d,"bitmap: 0x%8.8x, filter: 0x%8.8x\n",              p->egress_bitmap,p->egress_filter_bitmap);      bcm5600_port_bitmap_str(d,buffer,p->egress_bitmap);      /* without egress port filtering */      if (*buffer)         BCM_LOG(d,"forwarding to egress port list w/o filter: %s\n",buffer);      else         BCM_LOG(d,"w/o filter: empty egress port list.\n");      /* with egress port filtering */      bcm5600_port_bitmap_str(d,buffer,                              p->egress_bitmap & ~p->egress_filter_bitmap);      if (*buffer)         BCM_LOG(d,"forwarding to egress port list w/ filter: %s\n",buffer);   }#endif   return(p->egress_bitmap != 0);}/* Prototype for a packet sending function */typedef void (*bcm5600_send_pkt_t)(struct nm_16esw_data *d,                                   struct bcm5600_pkt *p,                                   netio_desc_t *nio);/* Directly forward a packet (not rewritten) */static void bcm5600_send_pkt_direct(struct nm_16esw_data *d,                                    struct bcm5600_pkt *p,                                    netio_desc_t *nio){   netio_send(nio,p->pkt,p->pkt_len);}/* Send a packet with a 802.1Q tag */static void bcm5600_send_pkt_push_dot1q(struct nm_16esw_data *d,                                        struct bcm5600_pkt *p,                                        netio_desc_t *nio){   n_eth_dot1q_hdr_t *hdr;   if (!p->rewrite_done) {      memcpy(p->rewr_pkt,p->pkt,(N_ETH_HLEN - 2));      hdr = (n_eth_dot1q_hdr_t *)p->rewr_pkt;      hdr->type    = htons(N_ETH_PROTO_DOT1Q);      hdr->vlan_id = htons(p->real_vlan);      memcpy(p->rewr_pkt + sizeof(n_eth_dot1q_hdr_t),             p->pkt + (N_ETH_HLEN - 2),             p->pkt_len - (N_ETH_HLEN - 2));      p->rewrite_done = TRUE;   }      netio_send(nio,p->rewr_pkt,p->pkt_len+4);}/* Send a packet deleting its 802.1Q tag */static void bcm5600_send_pkt_pop_dot1q(struct nm_16esw_data *d,                                       struct bcm5600_pkt *p,                                       netio_desc_t *nio){   if (!p->rewrite_done) {      memcpy(p->rewr_pkt,p->pkt,(N_ETH_HLEN - 2));      memcpy(p->rewr_pkt + (N_ETH_HLEN - 2),             p->pkt + sizeof(n_eth_dot1q_hdr_t),             p->pkt_len - sizeof(n_eth_dot1q_hdr_t));      p->rewrite_done = TRUE;   }      netio_send(nio,p->rewr_pkt,p->pkt_len-4);}/* Forward a packet on physical ports (egress bitmap must be defined) */static int bcm5600_forward_pkt(struct nm_16esw_data *d,struct bcm5600_pkt *p){   u_char rewr_pkt[BCM5600_MAX_PKT_SIZE];   bcm5600_send_pkt_t send_pkt;   u_int egress_untagged,trunk_id;   m_uint32_t *dst_port,*trunk;   int i;   p->egress_bitmap &= ~p->egress_filter_bitmap;      if (!p->egress_bitmap)      return(FALSE);   /* Process egress mirroring (if enabled) */   if (p->egress_bitmap & d->mirror_egress_ports)            bcm5600_mirror_pkt(d,p,1);   /* No rewrite done at this time */   p->rewr_pkt = rewr_pkt;   p->rewrite_done = FALSE;   /* Forward to CPU port ? */   if (p->egress_bitmap & (1 << d->cpu_port))      bcm5600_send_pkt_to_cpu(d,p);   for(i=0;i<d->nr_port;i++) {      if (!(p->egress_bitmap & (1 << i)))         continue;      /*        * If this port is a member of a trunk, remove all other ports to avoid       * duplicate frames (typically, when a dest MAC address is unknown       * or for a broadcast/multicast).       */      dst_port = bcm5600_table_get_entry(d,d->t_ptable,i);      assert(dst_port != NULL);      if (dst_port[0] & BCM5600_PTABLE_TRUNK_FLAG) {         trunk_id = dst_port[0] & BCM5600_PTABLE_TGID_MASK;         trunk_id >>= BCM5600_PTABLE_TGID_SHIFT;         trunk = bcm5600_table_get_entry(d,d->t_tbmap,trunk_id);         assert(trunk != NULL);                  p->egress_bitmap &= ~trunk[0];      }      /* select the appropriate output vector */      if (p->orig_vlan == 0)         send_pkt = bcm5600_send_pkt_direct;      else {         egress_untagged = p->egress_ut_bitmap & (1 << i);         if (p->orig_vlan == -1) {            /* Untagged packet */            if (egress_untagged)               send_pkt = bcm5600_send_pkt_direct;            else               send_pkt = bcm5600_send_pkt_push_dot1q;         } else {            /* Tagged packet */            if (egress_untagged)               send_pkt = bcm5600_send_pkt_pop_dot1q;            else               send_pkt = bcm5600_send_pkt_direct;         }      }#if DEBUG_FORWARD > 1      BCM_LOG(d,"forwarding on port %s (vector=%p)\n",              d->ports[i].name,send_pkt);#endif      send_pkt(d,p,d->ports[i].nio);   }   return(TRUE);}/* Handle a received packet */static int bcm5600_handle_rx_pkt(struct nm_16esw_data *d,struct bcm5600_pkt *p){   m_uint32_t *port_entry;   n_eth_dot1q_hdr_t *eth_hdr;   u_int discard;   /* No egress port at this time */   p->egress_bitmap = 0;   /* Never send back frames to the source port */   p->egress_filter_bitmap = 1 << p->ingress_port;   if (!(port_entry = bcm5600_table_get_entry(d,d->t_ptable,p->ingress_port)))      return(FALSE);   /* Analyze the Ethernet header */   eth_hdr = (n_eth_dot1q_hdr_t *)p->pkt;   /* Check for the reserved addresses (BPDU for spanning-tree) */   if (!memcmp(&eth_hdr->daddr,"\x01\x80\xc2\x00\x00",5) ||       !memcmp(&eth_hdr->daddr,"\x01\x00\x0c\xcc\xcc\xcd",6))   {#if DEBUG_RECEIVE      BCM_LOG(d,"Received a BPDU packet:\n");      mem_dump(d->vm->log_fd,p->pkt,p->pkt_len);#endif      p->orig_vlan = 0;      p->egress_bitmap |= 1 << d->cpu_port;      return(bcm5600_forward_pkt(d,p));   }   /* Discard packet ? */   discard = port_entry[0] & BCM5600_PTABLE_PRT_DIS_MASK;   discard >>= BCM5600_PTABLE_PRT_DIS_SHIFT;   if (discard) {      if (discard != 0x20) {         printf("\n\n\n"                "-----------------------------------------------------------"                "---------------------------------\n"                "Unspported feature: please post your current configuration "                "on http://www.ipflow.utc.fr/blog/\n"                "-----------------------------------------------------------"                "---------------------------------\n");      }      /* Drop the packet */      return(FALSE);   }   /* Mirroring on Ingress ? */   if (port_entry[1] & BCM5600_PTABLE_MI_FLAG)      bcm5600_mirror_pkt(d,p,0);   /* Determine VLAN */   if (ntohs(eth_hdr->type) != N_ETH_PROTO_DOT1Q) {      p->orig_vlan = -1;      p->real_vlan = port_entry[0] & BCM5600_PTABLE_VLAN_TAG_MASK;     if (!(p->vlan_entry = bcm5600_vtable_get_entry_by_vlan(d,p->real_vlan)))        return(FALSE);     /* TODO: 802.1p/CoS remarking */     if (port_entry[4] & BCM5600_PTABLE_RPE_FLAG) {     }   } else {      p->orig_vlan = p->real_vlan = ntohs(eth_hdr->vlan_id) & 0xFFF;      /* Check that this VLAN exists */      if (!(p->vlan_entry = bcm5600_vtable_get_entry_by_vlan(d,p->real_vlan)))         return(FALSE);      /* Check that this port is a member of this VLAN */      if (!(p->vlan_entry[1] & (1 << p->ingress_port)))         return(FALSE);   }#if DEBUG_RECEIVE   BCM_LOG(d,"%s: received a packet on VLAN %u\n",           d->ports[p->ingress_port].name,p->real_vlan);#endif   /* Source MAC address learning */   if (!bcm5600_src_mac_learning(d,p))      return(FALSE);   /* Take forwarding decision based on destination MAC address */   if (!bcm5600_dst_mac_lookup(d,p))      return(FALSE);   /* Send the packet to the egress ports */   return(bcm5600_forward_pkt(d,p));}/* Handle a packet to transmit */static int bcm5600_handle_tx_pkt(struct nm_16esw_data *d,                                 struct bcm5600_pkt *p,                                 u_int egress_bitmap){      n_eth_dot1q_hdr_t *eth_hdr;      /* Never send back frames to the source port */   p->egress_filter_bitmap = 1 << p->ingress_port;   /* We take the complete forwarding decision if bit 23 is set */   if (egress_bitmap & (1 << 23)) {      /* No egress port at this time */      p->egress_bitmap = 0;      /* The packet must be tagged so that we can determine the VLAN */      eth_hdr = (n_eth_dot1q_hdr_t *)p->pkt;      if (ntohs(eth_hdr->type) != N_ETH_PROTO_DOT1Q) {         BCM_LOG(d,"bcm5600_handle_tx_pkt: untagged packet ?\n");         return(FALSE);      }      /* Find the appropriate, check it exists (just in case) */      p->orig_vlan = p->real_vlan = ntohs(eth_hdr->vlan_id) & 0xFFF;      if (!(p->vlan_entry = bcm5600_vtable_get_entry_by_vlan(d,p->real_vlan)))        return(FALSE);#if DEBUG_TRANSMIT      BCM_LOG(d,"Transmitting a packet from TX ring to VLAN %u\n",              p->real_vlan);#endif      /* Take forwarding decision based on destination MAC address */      if (!bcm5600_dst_mac_lookup(d,p))         return(FALSE);   } else {#if DEBUG_TRANSMIT      BCM_LOG(d,"Transmitting natively a packet from TX ring.\n");#endif      /* The egress ports are specified, send the packet natively */      p->orig_vlan = 0;      p->egress_bitmap = egress_bitmap;   }   /* Send the packet to the egress ports */   return(bcm5600_forward_pkt(d,p));}/* Handle the TX ring */static int dev_bcm5600_handle_txring(struct nm_16esw_data *d){   struct bcm5600_pkt pkt_data;   m_uint32_t tdes[4],txd_len;   BCM_LOCK(d);   if (!d->tx_current || d->tx_end_scan) {      BCM_UNLOCK(d);      return(FALSE);   }   /* Read the current TX descriptor */   physmem_copy_from_vm(d->vm,tdes,d->tx_current,4*sizeof(m_uint32_t));   tdes[0] = vmtoh32(tdes[0]);   tdes[1] = vmtoh32(tdes[1]);   tdes[2] = vmtoh32(tdes[2]);   tdes[3] = vmtoh32(tdes[3]);   #if DEBUG_TRANSMIT   BCM_LOG(d,"=== TRANSMIT PATH ===\n");   BCM_LOG(d,"tx_current=0x%8.8x, "           "tdes[0]=0x%8.8x, tdes[1]=0x%8.8x, tdes[2]=0x%8.8x\n",           d->tx_current,tdes[0],tdes[1],tdes[2]);#endif   /* Get the buffer size */   txd_len = tdes[1] & 0x7FF;   /* Check buffer size */   if ((d->tx_bufsize + txd_len) >= sizeof(d->tx_buffer))      goto done;   /* Copy the packet from memory */   physmem_copy_from_vm(d->vm,d->tx_buffer+d->tx_bufsize,tdes[0],txd_len);   d->tx_bufsize += txd_len;   /* Packet not complete: handle it later */   if (tdes[1] & BCM5600_TXD_NEOP)      goto done;#if DEBUG_TRANSMIT   mem_dump(d->vm->log_fd,d->tx_buffer,d->tx_bufsize);#endif   /* Transmit the packet */   pkt_data.ingress_port = d->cpu_port;   pkt_data.pkt = d->tx_buffer;   pkt_data.pkt_len = d->tx_bufsize - 4;   pkt_data.sent_to_cpu = TRUE;   bcm5600_handle_tx_pkt(d,&pkt_data,tdes[2]);   /* Reset the TX buffer (packet fully transmitted) */   d->tx_bufsize = 0; done:   /* We have reached end of ring: trigger the TX underrun interrupt */   if (!(tdes[1] & BCM5600_TXD_RING_CONT)) {      d->tx_end_scan = 1;      pci_dev_trigger_irq(d->vm,d->pci_dev);      BCM_UNLOCK(d);      return(TRUE);   }    /* Go to the next descriptor */   d->tx_current += BCM5600_TXD_SIZE;   BCM_UNLOCK(d);      return(TRUE);}/* Handle the RX ring */static int dev_bcm5600_handle_rxring(netio_desc_t *nio,                                     u_char *pkt,ssize_t pkt_len,                                     struct nm_16esw_data *d,                                       struct bcm5600_port *port){     struct bcm5600_pkt pkt_data;   m_uint32_t rxd_len;#if DEBUG_RECEIVE   BCM_LOG(d,"=== RECEIVE PATH ===\n");   BCM_LOG(d,"%s: received a packet of %ld bytes.\n",           port->name,(u_long)pkt_len);   mem_dump(d->vm->log_fd,pkt,pkt_len);#endif   BCM_LOCK(d);   if (!d->rx_current || d->rx_end_scan) {      BCM_UNLOCK(d);      return(FALSE);   }      /* Read the current TX descriptor */   physmem_copy_from_vm(d->vm,pkt_data.rdes,d->rx_current,                        (4 * sizeof(m_uint32_t)));   pkt_data.rdes[0] = vmtoh32(pkt_data.rdes[0]);   pkt_data.rdes[1] = vmtoh32(pkt_data.rdes[1]);   pkt_data.rdes[2] = vmtoh32(pkt_data.rdes[2]);   pkt_data.rdes[3] = vmtoh32(pkt_data.rdes[3]);#if DEBUG_RECEIVE   BCM_LOG(d,"rx_current=0x%8.8x, "           "rdes[0]=0x%8.8x, rdes[1]=0x%8.8x, rdes[2]=0x%8.8x\n",           d->rx_current,pkt_data.rdes[0],pkt_data.rdes[1],pkt_data.rdes[2]);#endif   /* Get the buffer size */   rxd_len = pkt_data.rdes[1] & 0x7FF;   if (pkt_len > rxd_len) {      BCM_UNLOCK(d);      return(FALSE);   }   /* Fill the packet info */   pkt_data.ingress_port = port->id;   pkt_data.pkt = pkt;   pkt_data.pkt_len = pkt_len;   pkt_data.sent_to_cpu = FALSE;   /* Handle the packet */   bcm5600_handle_rx_pkt(d,&pkt_data);     /* Signal only an interrupt when a packet has been sent to the CPU */   if (pkt_data.sent_to_cpu) {      /* We have reached end of ring: trigger the RX underrun interrupt */      if (!(pkt_data.rdes[1] & BCM5600_RXD_RING_CONT)) {         d->rx_end_scan = 1;         pci_dev_trigger_irq(d->vm,d->pci_dev);         BCM_UNLOCK(d);         return(TRUE);      }      /* A packet was received */      pci_dev_trigger_irq(d->vm,d->pci_dev);      /* Go to the next descriptor */      d->rx_current += BCM5600_RXD_SIZE;   }   BCM_UNLOCK(d);   return(TRUE);}/* pci_bcm5605_read() */static m_uint32_t pci_bcm5605_read(cpu_mips_t *cpu,s

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -