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

📄 dev_nm_16esw.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 5 页
字号:
         BCM_LOG(d,"unknown s-chan command 0x%8.8x\n",cmd);#endif         d->schan_cmd_res = 0xFFFFFFFF;   }}/* * dev_bcm5605_access() */void *dev_bcm5605_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset,                         u_int op_size,u_int op_type,m_uint64_t *data){   struct nm_16esw_data *d = dev->priv_data;   u_int reg;   if (op_type == MTS_READ)      *data = 0;#if DEBUG_ACCESS   if (op_type == MTS_READ) {      BCM_LOG(d,"read  access to offset=0x%x, pc=0x%llx\n",offset,cpu->pc);   } else {      BCM_LOG(d,"write access to offset=0x%x, pc=0x%llx, val=0x%llx\n",              offset,cpu->pc,*data);   }#endif   BCM_LOCK(d);   switch(offset) {      case 0x50:         if (op_type == MTS_WRITE) {            bcm5600_handle_schan_cmd(d,*data);         } else {            *data = d->schan_cmd_res;         }         break;      case 0x140:         if (op_type == MTS_READ)            *data = bcm5600_mii_port_status_bmp(d);         break;      /* MII input register */      case 0x158:         if (op_type == MTS_WRITE)            d->mii_input = *data;         break;      /* MII output register */      case 0x15c:         if (op_type == MTS_READ)            *data = d->mii_output;         break;               /* Unknown (related to RX/TX rings ?) */      case 0x104:         break;      /* TX ring address */      case 0x110:         if (op_type == MTS_READ)            *data = d->tx_ring_addr;         else {            d->tx_ring_addr = d->tx_current = *data;               d->tx_end_scan = 0;#if DEBUG_TRANSMIT            BCM_LOG(d,"tx_ring_addr = 0x%8.8x\n",d->tx_ring_addr);#endif         }         break;      /* RX ring address */      case 0x114:         if (op_type == MTS_READ)            *data = d->rx_ring_addr;         else {            d->rx_ring_addr = d->rx_current = *data;            d->rx_end_scan = 0;#if DEBUG_RECEIVE            BCM_LOG(d,"rx_ring_addr = 0x%8.8x\n",d->rx_ring_addr);#endif         }         break;      /* Interrupt status */      case 0x144:         if (op_type == MTS_READ) {            *data = 0;            /* RX/TX underrun (end of rings reached) */            if (d->tx_end_scan)               *data |= BCM5600_INTR_TX_UNDERRUN;            if (d->rx_end_scan)               *data |= BCM5600_INTR_RX_UNDERRUN;            /* RX packet available */            *data |= BCM5600_INTR_RX_AVAIL;            /* Link status changed */            if (d->mii_intr) {               *data |= BCM5600_INTR_LINKSTAT_MOD;               d->mii_intr = FALSE;            }         }         break;      /* Interrupt mask */      case 0x148:         if (op_type == MTS_READ)            *data = d->intr_mask;         else            d->intr_mask = *data;         break;      /* Data Words */      case 0x800 ... 0x850:         reg = (offset - 0x800) >> 2;         if (op_type == MTS_READ)            *data = d->dw[reg];         else            d->dw[reg] = *data;         break;#if DEBUG_UNKNOWN      /* Unknown offset */      default:         if (op_type == MTS_READ) {            BCM_LOG(d,"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                    offset,cpu->pc,op_size);         } else {            BCM_LOG(d,"write to unknown addr 0x%x, value=0x%llx, "                    "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);         }#endif   }   BCM_UNLOCK(d);   return NULL;}/* Show mirroring status */static int bcm5600_mirror_show_status(struct nm_16esw_data *d){   m_uint32_t *port,dst_port;   int i;   printf("Mirroring status: ");    if (!(d->mirror_dst_port & BCM5600_MIRROR_ENABLE)) {      printf("disabled.\n\n");      return(FALSE);   }   printf("enabled. Dest port: ");   dst_port = d->mirror_dst_port & BCM5600_MIRROR_PORT_MASK;   if (dst_port < 32)      printf("%s\n",d->ports[dst_port].name);   else      printf("none set.\n");   /* Ingress info */   printf("  Ingress Ports: ");   for(i=0;i<d->nr_port;i++) {      port = bcm5600_table_get_entry(d,d->t_ptable,i);      if (port[1] & BCM5600_PTABLE_MI_FLAG)         printf("%s ",d->ports[i].name);   }   printf("\n");   /* Egress info */   printf("  Egress Ports: ");     for(i=0;i<d->nr_port;i++)      if (d->mirror_egress_ports & (1 << i))         printf("%s ",d->ports[i].name);   printf("\n\n");   return(TRUE);}/* Mirror a packet */static int bcm5600_mirror_pkt(struct nm_16esw_data *d,struct bcm5600_pkt *p,                              int reason){   u_int mport;   if (!(d->mirror_dst_port & BCM5600_MIRROR_ENABLE))      return(FALSE);#if DEBUG_MIRROR   if (reason == 0) {      BCM_LOG(d,"mirroring packet on ingress port %s\n",              d->ports[p->ingress_port]);   } else {      BCM_LOG(d,"mirroring packet on egress port (input port %s)\n",              d->ports[p->ingress_port]);   }   mem_dump(d->vm->log_fd,pkt,pkt_len);#endif   mport = d->mirror_dst_port & BCM5600_MIRROR_PORT_MASK;   if (mport < 32)      netio_send(d->ports[mport].nio,p->pkt,p->pkt_len);   return(TRUE);}/* Put a packet into the RX ring (tag it if necessary) */static int bcm5600_send_pkt_to_cpu(struct nm_16esw_data *d,                                   struct bcm5600_pkt *p){   m_uint32_t pkt_addr,pkt_len,dot1q_data;   /* If the packet was already sent to CPU, don't send it again */   if (p->sent_to_cpu)      return(FALSE);   pkt_addr = p->rdes[0];   pkt_len  = p->pkt_len;   if (p->orig_vlan != -1) {      /* 802.1Q packet: copy it directly */      physmem_copy_to_vm(d->vm,p->pkt,pkt_addr,pkt_len);   } else {      /* untagged packet: copy the dst and src addresses first */      physmem_copy_to_vm(d->vm,p->pkt,pkt_addr,N_ETH_HLEN - 2);      /* add the 802.1Q protocol field (0x8100) + VLAN info */      dot1q_data = (N_ETH_PROTO_DOT1Q << 16) | p->real_vlan;      physmem_copy_u32_to_vm(d->vm,pkt_addr+N_ETH_HLEN-2,dot1q_data);      /* copy the payload */      physmem_copy_to_vm(d->vm,p->pkt+N_ETH_HLEN-2,                         pkt_addr+sizeof(n_eth_dot1q_hdr_t),                         pkt_len - (N_ETH_HLEN - 2));      pkt_len += 4;   }   physmem_copy_u32_to_vm(d->vm,d->rx_current+0x14,0x40000000 + (pkt_len+4));   physmem_copy_u32_to_vm(d->vm,d->rx_current+0x18,0x100 + p->ingress_port);   p->sent_to_cpu = TRUE;#if DEBUG_RECEIVE   BCM_LOG(d,"sending packet to CPU (orig_vlan=%d).\n",p->orig_vlan);#endif   return(TRUE);}/* Source MAC address learning */static int bcm5600_src_mac_learning(struct nm_16esw_data *d,                                    struct bcm5600_pkt *p){     n_eth_hdr_t *eth_hdr = (n_eth_hdr_t *)p->pkt;   n_eth_addr_t *src_mac = &eth_hdr->saddr;   m_uint32_t *arl_entry,*src_port,*trunk;   u_int trunk_id,old_ingress_port;   int src_mac_index;   trunk = NULL;   trunk_id = 0;   /* Skip multicast sources */   if (eth_addr_is_mcast(src_mac))      return(FALSE);   src_port = bcm5600_table_get_entry(d,d->t_ptable,p->ingress_port);   assert(src_port != NULL);   /*     * The packet comes from a trunk port. Prevent sending the packet    * to the other ports of the trunk.    */   if (src_port[0] & BCM5600_PTABLE_TRUNK_FLAG) {      trunk_id = src_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_filter_bitmap |= trunk[0] & BCM5600_TBMAP_MASK;   }   /* Source MAC address learning */   src_mac_index = bcm5600_arl_lookup(d,src_mac,p->real_vlan);   if (src_mac_index != -1) {      arl_entry = bcm5600_table_get_entry(d,d->t_arl,src_mac_index);      assert(arl_entry != NULL);      old_ingress_port = arl_entry[2] & BCM5600_ARL_PORT_MASK;      old_ingress_port >>= BCM5600_ARL_PORT_SHIFT;      if (old_ingress_port != p->ingress_port)       {         /*          * Determine if we have a station movement.          * If we have a trunk, check if the old ingress port is member          * of this trunk, in this case this is not a movement.          */         if (trunk != NULL) {            if (trunk[0] & (1 << old_ingress_port))               arl_entry[2] |= BCM5600_ARL_HIT_FLAG;            else                arl_entry[2] &= ~BCM5600_ARL_HIT_FLAG;         } else {            arl_entry[2] &= ~(BCM5600_ARL_TRUNK_FLAG|BCM5600_ARL_HIT_FLAG);            arl_entry[2] &= ~BCM5600_ARL_TGID_MASK;         }         /* Change the ingress port */         arl_entry[2] &= ~BCM5600_ARL_PORT_MASK;         arl_entry[2] |= p->ingress_port << BCM5600_ARL_PORT_SHIFT;         return(TRUE);      }      arl_entry[2] |= BCM5600_ARL_HIT_FLAG;      return(TRUE);   }#if DEBUG_FORWARD      BCM_LOG(d,"source MAC address unknown, learning it.\n");#endif   /* Add the new learned MAC address */   src_mac_index = bcm5600_find_free_arl_entry(d);   if (src_mac_index == -1) {      BCM_LOG(d,"no free entries in ARL table!\n");      return(FALSE);   }   arl_entry = bcm5600_table_get_entry(d,d->t_arl,src_mac_index);   assert(arl_entry != NULL);       /* Fill the new ARL entry */   arl_entry[0]  = src_mac->eth_addr_byte[2] << 24;   arl_entry[0] |= src_mac->eth_addr_byte[3] << 16;   arl_entry[0] |= src_mac->eth_addr_byte[4] << 8;   arl_entry[0] |= src_mac->eth_addr_byte[5];   arl_entry[1]  = src_mac->eth_addr_byte[0] << 8;   arl_entry[1] |= src_mac->eth_addr_byte[1];   arl_entry[1] |= p->real_vlan << BCM5600_ARL_VLAN_TAG_SHIFT;   arl_entry[2]  = BCM5600_ARL_HIT_FLAG;   arl_entry[2] |= p->ingress_port << BCM5600_ARL_PORT_SHIFT;   if (trunk != NULL) {      arl_entry[2] |= BCM5600_ARL_TRUNK_FLAG;      arl_entry[2] |= (trunk_id << BCM5600_ARL_TGID_SHIFT);   }   d->arl_cnt[0]++;   return(TRUE);}/* Select an egress port the specified trunk */static int bcm5600_trunk_egress_port(struct nm_16esw_data *d,                                     struct bcm5600_pkt *p,                                     u_int trunk_id){      n_eth_hdr_t *eth_hdr = (n_eth_hdr_t *)p->pkt;   struct bcm5600_tg_info *tgi;   m_uint32_t *ttr_entry;   u_int i,nr_links;   u_int hash,port_id;   ttr_entry = bcm5600_table_get_entry(d,d->t_ttr,trunk_id);   assert(ttr_entry != NULL);   nr_links = ttr_entry[1] & BCM5600_TTR_TG_SIZE_MASK;   nr_links >>= BCM5600_TTR_TG_SIZE_SHIFT;#if 0   /* Hash on source and destination MAC addresses */   for(i=0,hash=0;i<N_ETH_ALEN;i++) {      hash ^= eth_hdr->saddr.eth_addr_byte[i];      hash ^= eth_hdr->daddr.eth_addr_byte[i];   }   hash ^= (hash >> 4);   port_id = hash % nr_links;   /* Maximum of 8 ports per trunk */   assert(hash < BCM5600_MAX_PORTS_PER_TRUNK);#else   port_id = d->trunk_last_egress_port[trunk_id] + 1;   port_id %= nr_links;   #endif   /* Save the latest port used for this trunk */   d->trunk_last_egress_port[trunk_id] = port_id;   /* Select the egress port */   tgi = &tg_info[port_id];   return((ttr_entry[tgi->index] & tgi->mask) >> tgi->shift);}/* Destination address lookup (take the forwarding decision) */static int bcm5600_dst_mac_lookup(struct nm_16esw_data *d,                                  struct bcm5600_pkt *p){   n_eth_hdr_t *eth_hdr = (n_eth_hdr_t *)p->pkt;   n_eth_addr_t *dst_mac = &eth_hdr->daddr;   struct bcm5600_table *arl_table;   m_uint32_t *arl_entry;   u_int egress_port;   u_int trunk_id;   int dst_mac_index;   int is_mcast;   /* Select the appropriate ARL table and do the lookup on dst MAC + VLAN */   if (eth_addr_is_mcast(dst_mac)) {      is_mcast = TRUE;      arl_table = d->t_marl;      dst_mac_index = bcm5600_marl_lookup(d,dst_mac,p->real_vlan);   } else {      is_mcast = FALSE;      arl_table = d->t_arl;      dst_mac_index = bcm5600_arl_lookup(d,dst_mac,p->real_vlan);   }   /*    * Destination Lookup Failure (DLF).    *     * Use the VLAN bitmap to compute the Egress port bitmap.    * Remove the ingress port from it.    */   if (dst_mac_index == -1) {#if DEBUG_FORWARD      BCM_LOG(d,"Destination MAC address unknown, flooding.\n");#endif      p->egress_bitmap = p->vlan_entry[1] & BCM5600_VTABLE_PORT_BMAP_MASK;      /* Add the CPU to the egress ports */      p->egress_bitmap |= 1 << d->cpu_port;      p->egress_ut_bitmap = p->vlan_entry[2];      p->egress_ut_bitmap &= BCM5600_VTABLE_UT_PORT_BMAP_MASK;      return(TRUE);   }   /* The MAC address was found in the ARL/MARL table */   arl_entry = bcm5600_table_get_entry(d,arl_table,dst_mac_index);   assert(arl_entry != NULL);   /* If the CPU bit is set, send a copy of the packet to the CPU */   if (arl_entry[1] & BCM5600_ARL_CPU_FLAG)      bcm5600_send_pkt_to_cpu(d,p);   if (!is_mcast) {      /* Unicast: send the packet to the port or trunk found in ARL table */      if (arl_entry[2] & BCM5600_ARL_TRUNK_FLAG) {         trunk_id = arl_entry[2] & BCM5600_ARL_TGID_MASK;         trunk_id >>= BCM5600_ARL_TGID_SHIFT;         /* Select an output port for this trunk */         egress_port = bcm5600_trunk_egress_port(d,p,trunk_id);#if DEBUG_FORWARD         BCM_LOG(d,"Sending packet to trunk port %u, egress port %u\n",                 trunk_id,egress_port);#endif      } else {         egress_port = arl_entry[2] & BCM5600_ARL_PORT_MASK;         egress_port >>= BCM5600_ARL_PORT_SHIFT;

⌨️ 快捷键说明

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