20 |
#include <assert.h> |
#include <assert.h> |
21 |
|
|
22 |
#include "utils.h" |
#include "utils.h" |
23 |
|
#include "timer.h" |
24 |
#include "net.h" |
#include "net.h" |
25 |
#include "net_io.h" |
#include "net_io.h" |
26 |
#include "ptask.h" |
#include "ptask.h" |
102 |
#define BCM5600_CMD_CPU_SHIFT 0 |
#define BCM5600_CMD_CPU_SHIFT 0 |
103 |
|
|
104 |
/* Memory zones */ |
/* Memory zones */ |
105 |
#define BCM5600_ADDR_ARLCNT 0x01000000 |
#define BCM5600_ADDR_ARLCNT0 0x01000000 |
106 |
|
#define BCM5600_ADDR_ARLCNT1 0x01100000 |
107 |
|
#define BCM5600_ADDR_ARLCNT2 0x01200000 |
108 |
#define BCM5600_ADDR_ARL0 0x02000000 |
#define BCM5600_ADDR_ARL0 0x02000000 |
109 |
#define BCM5600_ADDR_ARL1 0x02100000 |
#define BCM5600_ADDR_ARL1 0x02100000 |
110 |
#define BCM5600_ADDR_ARL2 0x02200000 |
#define BCM5600_ADDR_ARL2 0x02200000 |
364 |
netio_desc_t *nio; |
netio_desc_t *nio; |
365 |
u_int id; |
u_int id; |
366 |
char name[32]; |
char name[32]; |
|
|
|
|
/* Other info ? */ |
|
367 |
}; |
}; |
368 |
|
|
369 |
/* NM-16ESW private data */ |
/* NM-16ESW private data */ |
377 |
|
|
378 |
pthread_mutex_t lock; |
pthread_mutex_t lock; |
379 |
|
|
380 |
|
/* Ager task */ |
381 |
|
timer_id ager_tid; |
382 |
|
|
383 |
/* S-channel command and command result */ |
/* S-channel command and command result */ |
384 |
m_uint32_t schan_cmd,schan_cmd_res; |
m_uint32_t schan_cmd,schan_cmd_res; |
385 |
|
|
427 |
/* Current egress port of all trunks */ |
/* Current egress port of all trunks */ |
428 |
u_int trunk_last_egress_port[BCM5600_MAX_TRUNKS]; |
u_int trunk_last_egress_port[BCM5600_MAX_TRUNKS]; |
429 |
|
|
430 |
|
/* ARL count table */ |
431 |
|
m_uint32_t *arl_cnt; |
432 |
|
|
433 |
/* ARL (Address Resolution Logic) Table */ |
/* ARL (Address Resolution Logic) Table */ |
434 |
m_uint32_t *arl_table; |
m_uint32_t *arl_table; |
435 |
|
|
451 |
2, 0, 6, 4, 10, 8, 14, 12, 3, 1, 7, 5, 11, 9, 15, 13, |
2, 0, 6, 4, 10, 8, 14, 12, 3, 1, 7, 5, 11, 9, 15, 13, |
452 |
}; |
}; |
453 |
|
|
|
/* NM-16ESW: 16 Ethernet port switch module */ |
|
|
static m_uint16_t eeprom_c3600_nm_16esw_data[] = { |
|
|
0x04FF, 0x4002, 0xA941, 0x0100, 0xC046, 0x0320, 0x003B, 0x3401, |
|
|
0x4245, 0x3080, 0x0000, 0x0000, 0x0203, 0xC18B, 0x464F, 0x4330, |
|
|
0x3931, 0x3132, 0x454E, 0x3803, 0x0081, 0x0000, 0x0000, 0x0400, |
|
|
0xCF06, 0x0013, 0x1A1D, 0x0BD1, 0x4300, 0x11FF, 0xFFFF, 0xFFFF, |
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
|
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
|
|
}; |
|
|
|
|
|
static const struct c3600_eeprom eeprom_c3600_nm_16esw = { |
|
|
"NM-16ESW", (m_uint16_t *)eeprom_c3600_nm_16esw_data, |
|
|
sizeof(eeprom_c3600_nm_16esw_data)/2, |
|
|
}; |
|
|
|
|
454 |
/* Log a BCM message */ |
/* Log a BCM message */ |
455 |
#define BCM_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg) |
#define BCM_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg) |
456 |
|
|
514 |
d->mii_output |= 0x1000; /* autoneg */ |
d->mii_output |= 0x1000; /* autoneg */ |
515 |
break; |
break; |
516 |
case 0x01: |
case 0x01: |
517 |
if (bcm5600_mii_port_status(d,port)) |
if (d->ports[port].nio && bcm5600_mii_port_status(d,port)) |
518 |
d->mii_output = 0x782C; |
d->mii_output = 0x782C; |
519 |
else |
else |
520 |
d->mii_output = 0; |
d->mii_output = 0; |
641 |
case 0x8000d: |
case 0x8000d: |
642 |
d->mirror_egress_ports = value; |
d->mirror_egress_ports = value; |
643 |
break; |
break; |
644 |
|
|
645 |
|
case 0x80009: |
646 |
|
/* age timer */ |
647 |
|
break; |
648 |
} |
} |
649 |
} |
} |
650 |
|
|
698 |
|
|
699 |
static struct bcm5600_table bcm5600_tables[] = { |
static struct bcm5600_table bcm5600_tables[] = { |
700 |
/* ARL tables */ |
/* ARL tables */ |
701 |
{ "arl0", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL0, 1, 8191, 3 }, |
{ "arlcnt0", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT0, 0, 0, 1 }, |
702 |
{ "arl1", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL1, 1, 8191, 3 }, |
{ "arlcnt1", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT1, 0, 0, 1 }, |
703 |
{ "arl2", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL2, 1, 8191, 3 }, |
{ "arlcnt2", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT2, 0, 0, 1 }, |
704 |
|
|
705 |
|
/* ARL tables */ |
706 |
|
{ "arl0", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL0, 0, 8191, 3 }, |
707 |
|
{ "arl1", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL1, 0, 8191, 3 }, |
708 |
|
{ "arl2", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL2, 0, 8191, 3 }, |
709 |
|
|
710 |
/* Multicast ARL tables */ |
/* Multicast ARL tables */ |
711 |
{ "marl0", BCM_OFFSET(marl_table), BCM5600_ADDR_MARL0, 1, 255, 5 }, |
{ "marl0", BCM_OFFSET(marl_table), BCM5600_ADDR_MARL0, 1, 255, 5 }, |
1082 |
static int bcm5600_find_free_arl_entry(struct nm_16esw_data *d) |
static int bcm5600_find_free_arl_entry(struct nm_16esw_data *d) |
1083 |
{ |
{ |
1084 |
struct bcm5600_table *table = d->t_arl; |
struct bcm5600_table *table = d->t_arl; |
|
m_uint32_t *entry; |
|
|
u_int vlan; |
|
|
int i; |
|
1085 |
|
|
1086 |
for(i=table->min_index;i<=table->max_index;i++) { |
if (d->arl_cnt[0] == table->max_index) |
1087 |
entry = bcm5600_table_get_entry(d,table,i); |
return(-1); |
|
|
|
|
vlan = (entry[1] & BCM5600_ARL_VLAN_TAG_MASK); |
|
|
vlan >>= BCM5600_ARL_VLAN_TAG_SHIFT; |
|
|
|
|
|
if (vlan == 0xFFF) |
|
|
return(i); |
|
|
} |
|
1088 |
|
|
1089 |
return(-1); |
return(d->arl_cnt[0] - 1); |
1090 |
} |
} |
1091 |
|
|
1092 |
/* ARL Lookup. TODO: this must be optimized in the future. */ |
/* ARL Lookup. TODO: this must be optimized in the future. */ |
1093 |
static inline int bcm5600_gen_arl_lookup(struct nm_16esw_data *d, |
static inline int bcm5600_gen_arl_lookup(struct nm_16esw_data *d, |
1094 |
struct bcm5600_table *table, |
struct bcm5600_table *table, |
1095 |
|
u_int index_start,u_int index_end, |
1096 |
n_eth_addr_t *mac_addr, |
n_eth_addr_t *mac_addr, |
1097 |
u_int vlan) |
u_int vlan) |
1098 |
{ |
{ |
1109 |
|
|
1110 |
mask = BCM5600_ARL_VLAN_TAG_MASK | BCM5600_ARL_MAC_MSB_MASK; |
mask = BCM5600_ARL_VLAN_TAG_MASK | BCM5600_ARL_MAC_MSB_MASK; |
1111 |
|
|
1112 |
for(i=table->min_index;i<=table->max_index;i++) { |
for(i=index_start;i<index_end;i++) { |
1113 |
entry = bcm5600_table_get_entry(d,table,i); |
entry = bcm5600_table_get_entry(d,table,i); |
1114 |
|
|
1115 |
if ((entry[0] == tmp[0]) && ((entry[1] & mask) == tmp[1])) |
if ((entry[0] == tmp[0]) && ((entry[1] & mask) == tmp[1])) |
1124 |
n_eth_addr_t *mac_addr, |
n_eth_addr_t *mac_addr, |
1125 |
u_int vlan) |
u_int vlan) |
1126 |
{ |
{ |
1127 |
return(bcm5600_gen_arl_lookup(d,d->t_arl,mac_addr,vlan)); |
struct bcm5600_table *table = d->t_arl; |
1128 |
|
return(bcm5600_gen_arl_lookup(d,table,1,d->arl_cnt[0]-1,mac_addr,vlan)); |
1129 |
} |
} |
1130 |
|
|
1131 |
/* MARL Lookup */ |
/* MARL Lookup */ |
1133 |
n_eth_addr_t *mac_addr, |
n_eth_addr_t *mac_addr, |
1134 |
u_int vlan) |
u_int vlan) |
1135 |
{ |
{ |
1136 |
return(bcm5600_gen_arl_lookup(d,d->t_marl,mac_addr,vlan)); |
struct bcm5600_table *table = d->t_marl; |
1137 |
|
return(bcm5600_gen_arl_lookup(d,table,table->min_index,table->max_index+1, |
1138 |
|
mac_addr,vlan)); |
1139 |
|
} |
1140 |
|
|
1141 |
|
/* Invalidate an ARL entry */ |
1142 |
|
static void bcm5600_invalidate_arl_entry(m_uint32_t *entry) |
1143 |
|
{ |
1144 |
|
entry[0] = entry[1] = entry[2] = 0; |
1145 |
} |
} |
1146 |
|
|
1147 |
/* Insert an entry into the ARL table */ |
/* Insert an entry into the ARL table */ |
1148 |
static int bcm5600_insert_arl_entry(struct nm_16esw_data *d) |
static int bcm5600_insert_arl_entry(struct nm_16esw_data *d) |
1149 |
{ |
{ |
1150 |
struct bcm5600_table *table = d->t_arl; |
struct bcm5600_table *table = d->t_arl; |
1151 |
m_uint32_t *entry; |
m_uint32_t *entry,mask; |
1152 |
int index; |
int i,index; |
1153 |
|
|
1154 |
if ((index = bcm5600_find_free_arl_entry(d)) == -1) |
mask = BCM5600_ARL_VLAN_TAG_MASK | BCM5600_ARL_MAC_MSB_MASK; |
1155 |
return(-1); |
|
1156 |
|
for(i=0;i<d->arl_cnt[0]-1;i++) { |
1157 |
|
entry = bcm5600_table_get_entry(d,table,i); |
1158 |
|
|
1159 |
|
/* If entry already exists, just modify it */ |
1160 |
|
if ((entry[0] == d->dw[1]) && ((entry[1] & mask) == (d->dw[2] & mask))) { |
1161 |
|
entry[0] = d->dw[1]; |
1162 |
|
entry[1] = d->dw[2]; |
1163 |
|
entry[2] = d->dw[3]; |
1164 |
|
d->dw[1] = i; |
1165 |
|
return(0); |
1166 |
|
} |
1167 |
|
} |
1168 |
|
|
1169 |
|
index = d->arl_cnt[0] - 1; |
1170 |
|
|
1171 |
entry = bcm5600_table_get_entry(d,table,index); |
entry = bcm5600_table_get_entry(d,table,index); |
1172 |
entry[0] = d->dw[1]; |
entry[0] = d->dw[1]; |
1173 |
entry[1] = d->dw[2]; |
entry[1] = d->dw[2]; |
1174 |
entry[2] = d->dw[3]; |
entry[2] = d->dw[3]; |
1175 |
d->dw[1] = index; |
d->dw[1] = index; |
1176 |
|
|
1177 |
|
d->arl_cnt[0]++; |
1178 |
return(0); |
return(0); |
1179 |
} |
} |
1180 |
|
|
1182 |
static int bcm5600_delete_arl_entry(struct nm_16esw_data *d) |
static int bcm5600_delete_arl_entry(struct nm_16esw_data *d) |
1183 |
{ |
{ |
1184 |
struct bcm5600_table *table; |
struct bcm5600_table *table; |
1185 |
m_uint32_t *entry,mac_msb; |
m_uint32_t *entry,*last_entry,mac_msb; |
1186 |
u_int cvlan,vlan; |
u_int cvlan,vlan; |
1187 |
int i; |
int i; |
1188 |
|
|
1204 |
if ((cvlan == vlan) && (entry[0] == d->dw[1]) && |
if ((cvlan == vlan) && (entry[0] == d->dw[1]) && |
1205 |
((entry[1] & BCM5600_ARL_MAC_MSB_MASK) == mac_msb)) |
((entry[1] & BCM5600_ARL_MAC_MSB_MASK) == mac_msb)) |
1206 |
{ |
{ |
|
entry[0] = 0xFFFFFFFF; |
|
|
entry[1] = (VLAN_INVALID << BCM5600_ARL_VLAN_TAG_SHIFT) | 0xFFFF; |
|
|
entry[2] = 0; |
|
|
|
|
1207 |
d->dw[1] = i; |
d->dw[1] = i; |
1208 |
|
|
1209 |
|
last_entry = bcm5600_table_get_entry(d,d->t_arl,d->arl_cnt[0]-2); |
1210 |
|
|
1211 |
|
entry[0] = last_entry[0]; |
1212 |
|
entry[1] = last_entry[1]; |
1213 |
|
entry[2] = last_entry[2]; |
1214 |
|
|
1215 |
|
d->arl_cnt[0]--; |
1216 |
return(i); |
return(i); |
1217 |
} |
} |
1218 |
} |
} |
1222 |
|
|
1223 |
/* Reset the ARL tables */ |
/* Reset the ARL tables */ |
1224 |
static int bcm5600_reset_arl(struct nm_16esw_data *d) |
static int bcm5600_reset_arl(struct nm_16esw_data *d) |
1225 |
{ |
{ |
1226 |
struct bcm5600_table *table; |
struct bcm5600_table *table; |
1227 |
m_uint32_t *entry; |
m_uint32_t *entry; |
1228 |
int i; |
int i; |
1232 |
|
|
1233 |
for(i=table->min_index;i<=table->max_index;i++) { |
for(i=table->min_index;i<=table->max_index;i++) { |
1234 |
entry = bcm5600_table_get_entry(d,table,i); |
entry = bcm5600_table_get_entry(d,table,i); |
1235 |
|
bcm5600_invalidate_arl_entry(entry); |
|
entry[0] = 0xFFFFFFFF; |
|
|
entry[1] = (VLAN_INVALID << BCM5600_ARL_VLAN_TAG_SHIFT) | 0xFFFF; |
|
|
entry[2] = 0; |
|
1236 |
} |
} |
1237 |
|
|
1238 |
return(0); |
return(0); |
1239 |
} |
} |
1240 |
|
|
1241 |
|
/* MAC Address Ager */ |
1242 |
|
static int bcm5600_arl_ager(struct nm_16esw_data *d) |
1243 |
|
{ |
1244 |
|
m_uint32_t *entry,*last_entry; |
1245 |
|
int i; |
1246 |
|
|
1247 |
|
BCM_LOCK(d); |
1248 |
|
|
1249 |
|
for(i=1;i<d->arl_cnt[0]-1;i++) { |
1250 |
|
entry = bcm5600_table_get_entry(d,d->t_arl,i); |
1251 |
|
assert(entry); |
1252 |
|
|
1253 |
|
if (entry[2] & BCM5600_ARL_ST_FLAG) |
1254 |
|
continue; |
1255 |
|
|
1256 |
|
/* The entry has expired, purge it */ |
1257 |
|
if (!(entry[2] & BCM5600_ARL_HIT_FLAG)) { |
1258 |
|
last_entry = bcm5600_table_get_entry(d,d->t_arl,d->arl_cnt[0]-2); |
1259 |
|
|
1260 |
|
entry[0] = last_entry[0]; |
1261 |
|
entry[1] = last_entry[1]; |
1262 |
|
entry[2] = last_entry[2]; |
1263 |
|
|
1264 |
|
d->arl_cnt[0]--; |
1265 |
|
i--; |
1266 |
|
} else { |
1267 |
|
entry[2] &= ~BCM5600_ARL_HIT_FLAG; |
1268 |
|
} |
1269 |
|
} |
1270 |
|
|
1271 |
|
BCM_UNLOCK(d); |
1272 |
|
return(TRUE); |
1273 |
|
} |
1274 |
|
|
1275 |
/* Get the VTABLE entry matching the specified VLAN */ |
/* Get the VTABLE entry matching the specified VLAN */ |
1276 |
static m_uint32_t *bcm5600_vtable_get_entry_by_vlan(struct nm_16esw_data *d, |
static m_uint32_t *bcm5600_vtable_get_entry_by_vlan(struct nm_16esw_data *d, |
1277 |
u_int vlan) |
u_int vlan) |
1297 |
int i; |
int i; |
1298 |
|
|
1299 |
if (bcm5600_table_read_entry(d) != 0) { |
if (bcm5600_table_read_entry(d) != 0) { |
1300 |
for(i=0;i<BCM5600_DW_MAX;i++) |
for(i=1;i<BCM5600_DW_MAX;i++) |
1301 |
d->dw[i] = 0; |
d->dw[i] = 0; |
1302 |
} |
} |
1303 |
|
|
1749 |
src_mac_index = bcm5600_find_free_arl_entry(d); |
src_mac_index = bcm5600_find_free_arl_entry(d); |
1750 |
|
|
1751 |
if (src_mac_index == -1) { |
if (src_mac_index == -1) { |
1752 |
#if DEBUG_FORWARD |
BCM_LOG(d,"no free entries in ARL table!\n"); |
|
BCM_LOG(d,"no free entries in ARL table.\n"); |
|
|
#endif |
|
1753 |
return(FALSE); |
return(FALSE); |
1754 |
} |
} |
1755 |
|
|
1774 |
arl_entry[2] |= (trunk_id << BCM5600_ARL_TGID_SHIFT); |
arl_entry[2] |= (trunk_id << BCM5600_ARL_TGID_SHIFT); |
1775 |
} |
} |
1776 |
|
|
1777 |
|
d->arl_cnt[0]++; |
1778 |
return(TRUE); |
return(TRUE); |
1779 |
} |
} |
1780 |
|
|
1833 |
int dst_mac_index; |
int dst_mac_index; |
1834 |
int is_mcast; |
int is_mcast; |
1835 |
|
|
1836 |
/* Check for the reserved addresses (BPDU for spanning-tree) */ |
/* Select the appropriate ARL table and do the lookup on dst MAC + VLAN */ |
|
if (!memcmp(ð_hdr->daddr,"\x01\x80\xc2\x00\x00",5)) { |
|
|
p->egress_bitmap |= 1 << d->cpu_port; |
|
|
return(TRUE); |
|
|
} |
|
|
|
|
|
/* Select the appropriate ARL table */ |
|
1837 |
if (eth_addr_is_mcast(dst_mac)) { |
if (eth_addr_is_mcast(dst_mac)) { |
1838 |
is_mcast = TRUE; |
is_mcast = TRUE; |
1839 |
arl_table = d->t_marl; |
arl_table = d->t_marl; |
1840 |
|
dst_mac_index = bcm5600_marl_lookup(d,dst_mac,p->real_vlan); |
1841 |
} else { |
} else { |
1842 |
is_mcast = FALSE; |
is_mcast = FALSE; |
1843 |
arl_table = d->t_arl; |
arl_table = d->t_arl; |
1844 |
|
dst_mac_index = bcm5600_arl_lookup(d,dst_mac,p->real_vlan); |
1845 |
} |
} |
1846 |
|
|
|
/* ARL Lookup for this MAC address + VLAN */ |
|
|
dst_mac_index = bcm5600_gen_arl_lookup(d,arl_table,dst_mac,p->real_vlan); |
|
|
|
|
1847 |
/* |
/* |
1848 |
* Destination Lookup Failure (DLF). |
* Destination Lookup Failure (DLF). |
1849 |
* |
* |
2065 |
{ |
{ |
2066 |
m_uint32_t *port_entry; |
m_uint32_t *port_entry; |
2067 |
n_eth_dot1q_hdr_t *eth_hdr; |
n_eth_dot1q_hdr_t *eth_hdr; |
2068 |
|
u_int discard; |
2069 |
|
|
2070 |
|
/* No egress port at this time */ |
2071 |
|
p->egress_bitmap = 0; |
2072 |
|
|
2073 |
|
/* Never send back frames to the source port */ |
2074 |
|
p->egress_filter_bitmap = 1 << p->ingress_port; |
2075 |
|
|
2076 |
if (!(port_entry = bcm5600_table_get_entry(d,d->t_ptable,p->ingress_port))) |
if (!(port_entry = bcm5600_table_get_entry(d,d->t_ptable,p->ingress_port))) |
2077 |
return(FALSE); |
return(FALSE); |
2078 |
|
|
2079 |
|
/* Analyze the Ethernet header */ |
2080 |
eth_hdr = (n_eth_dot1q_hdr_t *)p->pkt; |
eth_hdr = (n_eth_dot1q_hdr_t *)p->pkt; |
2081 |
|
|
2082 |
|
/* Check for the reserved addresses (BPDU for spanning-tree) */ |
2083 |
|
if (!memcmp(ð_hdr->daddr,"\x01\x80\xc2\x00\x00",5)) { |
2084 |
|
p->egress_bitmap |= 1 << d->cpu_port; |
2085 |
|
return(bcm5600_forward_pkt(d,p)); |
2086 |
|
} |
2087 |
|
|
2088 |
|
/* Discard packet ? */ |
2089 |
|
discard = port_entry[0] & BCM5600_PTABLE_PRT_DIS_MASK; |
2090 |
|
discard >>= BCM5600_PTABLE_PRT_DIS_SHIFT; |
2091 |
|
|
2092 |
|
if (discard) { |
2093 |
|
if (discard != 0x20) { |
2094 |
|
printf("\n\n\n" |
2095 |
|
"-----------------------------------------------------------" |
2096 |
|
"---------------------------------\n" |
2097 |
|
"Unspported feature: please post your current configuration " |
2098 |
|
"on http://www.ipflow.utc.fr/blog/\n" |
2099 |
|
"-----------------------------------------------------------" |
2100 |
|
"---------------------------------\n"); |
2101 |
|
} |
2102 |
|
|
2103 |
|
/* Drop the packet */ |
2104 |
|
return(FALSE); |
2105 |
|
} |
2106 |
|
|
2107 |
/* Mirroring on Ingress ? */ |
/* Mirroring on Ingress ? */ |
2108 |
if (port_entry[1] & BCM5600_PTABLE_MI_FLAG) |
if (port_entry[1] & BCM5600_PTABLE_MI_FLAG) |
2109 |
bcm5600_mirror_pkt(d,p,0); |
bcm5600_mirror_pkt(d,p,0); |
2136 |
d->ports[p->ingress_port].name,p->real_vlan); |
d->ports[p->ingress_port].name,p->real_vlan); |
2137 |
#endif |
#endif |
2138 |
|
|
|
/* 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; |
|
|
|
|
2139 |
/* Source MAC address learning */ |
/* Source MAC address learning */ |
2140 |
if (!bcm5600_src_mac_learning(d,p)) |
if (!bcm5600_src_mac_learning(d,p)) |
2141 |
return(FALSE); |
return(FALSE); |
2154 |
u_int egress_bitmap) |
u_int egress_bitmap) |
2155 |
{ |
{ |
2156 |
n_eth_dot1q_hdr_t *eth_hdr; |
n_eth_dot1q_hdr_t *eth_hdr; |
|
|
|
|
{ |
|
|
eth_hdr = (n_eth_dot1q_hdr_t *)p->pkt; |
|
|
|
|
|
if (ntohs(eth_hdr->type) == 0x9000) { |
|
|
printf("bcm5600_handle_tx_pkt: KEEPALIVE ????\n"); |
|
|
return(FALSE); |
|
|
} |
|
|
} |
|
2157 |
|
|
2158 |
/* Never send back frames to the source port */ |
/* Never send back frames to the source port */ |
2159 |
p->egress_filter_bitmap = 1 << p->ingress_port; |
p->egress_filter_bitmap = 1 << p->ingress_port; |
2372 |
} |
} |
2373 |
} |
} |
2374 |
|
|
2375 |
|
/* Rewrite the base MAC address */ |
2376 |
|
static int dev_c3600_nm_16esw_burn_mac_addr(c3600_t *router,u_int nm_bay) |
2377 |
|
{ |
2378 |
|
struct cisco_eeprom *eeprom; |
2379 |
|
m_uint8_t eeprom_ver; |
2380 |
|
size_t offset; |
2381 |
|
n_eth_addr_t addr; |
2382 |
|
m_uint16_t pid; |
2383 |
|
|
2384 |
|
pid = (m_uint16_t)getpid(); |
2385 |
|
|
2386 |
|
/* Generate automatically the MAC address */ |
2387 |
|
addr.eth_addr_byte[0] = 0xCE; |
2388 |
|
addr.eth_addr_byte[1] = router->vm->instance_id & 0xFF; |
2389 |
|
addr.eth_addr_byte[2] = pid >> 8; |
2390 |
|
addr.eth_addr_byte[3] = pid & 0xFF; |
2391 |
|
addr.eth_addr_byte[4] = nm_bay; |
2392 |
|
addr.eth_addr_byte[5] = 0x00; |
2393 |
|
|
2394 |
|
/* Modify the EEPROM data which have been duplicated */ |
2395 |
|
eeprom = &router->nm_bay[nm_bay].eeprom; |
2396 |
|
|
2397 |
|
/* Read EEPROM format version */ |
2398 |
|
cisco_eeprom_get_byte(eeprom,0,&eeprom_ver); |
2399 |
|
|
2400 |
|
if (eeprom_ver != 4) |
2401 |
|
return(-1); |
2402 |
|
|
2403 |
|
if (cisco_eeprom_v4_find_field(eeprom,0xCF,&offset) == -1) |
2404 |
|
return(-1); |
2405 |
|
|
2406 |
|
cisco_eeprom_set_region(eeprom,offset,addr.eth_addr_byte,6); |
2407 |
|
return(0); |
2408 |
|
} |
2409 |
|
|
2410 |
/* Initialize a NM-16ESW module */ |
/* Initialize a NM-16ESW module */ |
2411 |
static int dev_c3600_nm_16esw_init(c3600_t *router,char *name,u_int nm_bay) |
static int dev_c3600_nm_16esw_init(c3600_t *router,char *name,u_int nm_bay) |
2412 |
{ |
{ |
2434 |
|
|
2435 |
/* Clear the various tables */ |
/* Clear the various tables */ |
2436 |
bcm5600_reset_arl(data); |
bcm5600_reset_arl(data); |
2437 |
|
data->arl_cnt[0] = 1; |
2438 |
data->t_ptable = bcm5600_table_find(data,BCM5600_ADDR_PTABLE0); |
data->t_ptable = bcm5600_table_find(data,BCM5600_ADDR_PTABLE0); |
2439 |
data->t_vtable = bcm5600_table_find(data,BCM5600_ADDR_VTABLE0); |
data->t_vtable = bcm5600_table_find(data,BCM5600_ADDR_VTABLE0); |
2440 |
data->t_arl = bcm5600_table_find(data,BCM5600_ADDR_ARL0); |
data->t_arl = bcm5600_table_find(data,BCM5600_ADDR_ARL0); |
2454 |
} |
} |
2455 |
|
|
2456 |
/* Set the EEPROM */ |
/* Set the EEPROM */ |
2457 |
c3600_nm_set_eeprom(router,nm_bay,&eeprom_c3600_nm_16esw); |
c3600_nm_set_eeprom(router,nm_bay,cisco_eeprom_find_nm("NM-16ESW")); |
2458 |
|
dev_c3600_nm_16esw_burn_mac_addr(router,nm_bay); |
2459 |
|
|
2460 |
/* Get PCI bus info about this bay */ |
/* Get PCI bus info about this bay */ |
2461 |
bay_info = c3600_nm_get_bay_info(c3600_chassis_get_id(router),nm_bay); |
bay_info = c3600_nm_get_bay_info(c3600_chassis_get_id(router),nm_bay); |
2494 |
data->tx_tid = ptask_add((ptask_callback)dev_bcm5606_handle_txring, |
data->tx_tid = ptask_add((ptask_callback)dev_bcm5606_handle_txring, |
2495 |
data,NULL); |
data,NULL); |
2496 |
|
|
2497 |
|
/* Start the MAC address ager */ |
2498 |
|
data->ager_tid = timer_create_entry(15000,FALSE,10, |
2499 |
|
(timer_proc)bcm5600_arl_ager,data); |
2500 |
|
|
2501 |
/* Store device info into the router structure */ |
/* Store device info into the router structure */ |
2502 |
return(c3600_nm_set_drvinfo(router,nm_bay,data)); |
return(c3600_nm_set_drvinfo(router,nm_bay,data)); |
2503 |
} |
} |
2516 |
/* Remove the NM EEPROM */ |
/* Remove the NM EEPROM */ |
2517 |
c3600_nm_unset_eeprom(router,nm_bay); |
c3600_nm_unset_eeprom(router,nm_bay); |
2518 |
|
|
2519 |
|
/* Stop the Ager */ |
2520 |
|
timer_remove(data->ager_tid); |
2521 |
|
|
2522 |
/* Stop the TX ring task */ |
/* Stop the TX ring task */ |
2523 |
ptask_remove(data->tx_tid); |
ptask_remove(data->tx_tid); |
2524 |
|
|
2579 |
return(-1); |
return(-1); |
2580 |
|
|
2581 |
BCM_LOCK(d); |
BCM_LOCK(d); |
2582 |
|
printf("ARL count = %u\n\n",d->arl_cnt[0]); |
2583 |
bcm5600_dump_main_tables(d); |
bcm5600_dump_main_tables(d); |
2584 |
bcm5600_mirror_show_status(d); |
bcm5600_mirror_show_status(d); |
2585 |
bcm5600_reg_dump(d,FALSE); |
bcm5600_reg_dump(d,FALSE); |