diff --git a/html/app.js b/html/app.js index 626e522c..3d499b38 100644 --- a/html/app.js +++ b/html/app.js @@ -11,7 +11,7 @@ th_sel_light:"Selenized Light",th_sel_dark:"Selenized Dark", c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Apply",c_cancel:"Cancel",c_confirm:"Confirm", c_close:"Close",c_refresh:"Refresh",c_off:"off",c_offc:"Off",c_down:"down",c_on:"On",c_auto:"Auto",c_delete:"Delete", c_type:"Type",c_state:"State",c_enabled:"Enabled",c_load:"Load",c_disable:"Disable",c_sfp:"SFP", -c_full:"full",c_half:"half",c_devices:"devices",c_yes:"yes",c_no:"no", +c_full:"full",c_half:"half",c_yes:"yes",c_no:"no", d_ports:"Ports",d_ports_h:"click a port for details",d_system:"System",d_traffic:"Traffic", d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad", i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware", @@ -19,7 +19,7 @@ i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"S p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad", p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power", p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising", -pt_title:"Port configuration",pt_conn:"Connected",pt_speed:"Speed",pt_mtu:"MTU", +pt_title:"Port configuration",pt_conn:"Devices learned",pt_speed:"Speed",pt_mtu:"MTU", pt_sfp_note:"SFP speed is set per slot and is not saved in the startup config.", pt_name_err:"Port name: 1-15 characters, no spaces",pt_mtu_err:"MTU must be 64-16383", stp_title:"Spanning tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP compatible", @@ -142,7 +142,7 @@ th_sel_light:"Selenized ライト",th_sel_dark:"Selenized ダーク", c_port:"ポート",c_name:"名前",c_link:"リンク",c_apply:"適用",c_cancel:"キャンセル",c_confirm:"確認", c_close:"閉じる",c_refresh:"更新",c_off:"オフ",c_offc:"オフ",c_down:"リンクダウン",c_on:"オン",c_auto:"自動",c_delete:"削除", c_type:"タイプ",c_state:"状態",c_enabled:"有効",c_load:"読み込み",c_disable:"無効化",c_sfp:"SFP", -c_full:"全二重",c_half:"半二重",c_devices:"デバイス",c_yes:"はい",c_no:"いいえ", +c_full:"全二重",c_half:"半二重",c_yes:"はい",c_no:"いいえ", d_ports:"ポート",d_ports_h:"ポートをクリックすると詳細を表示",d_system:"システム",d_traffic:"トラフィック", d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常", i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア", @@ -150,7 +150,7 @@ i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラ p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常", p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力", p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ", -pt_title:"ポート設定",pt_conn:"接続デバイス",pt_speed:"速度",pt_mtu:"MTU", +pt_title:"ポート設定",pt_conn:"学習済みデバイス",pt_speed:"速度",pt_mtu:"MTU", pt_sfp_note:"SFP の速度はスロット単位で設定され、起動設定には保存されません。", pt_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください", stp_title:"スパニングツリー",stp_h:"RSTP, 802.1w",stp_version:"バージョン",stp_v_stp:"STP 互換", @@ -255,7 +255,7 @@ th_sel_light:"Selenized 浅色",th_sel_dark:"Selenized 深色", c_port:"端口",c_name:"名称",c_link:"链路",c_apply:"应用",c_cancel:"取消",c_confirm:"确认", c_close:"关闭",c_refresh:"刷新",c_off:"关",c_offc:"关",c_down:"未连接",c_on:"开",c_auto:"自动",c_delete:"删除", c_type:"类型",c_state:"状态",c_enabled:"启用",c_load:"读取",c_disable:"禁用",c_sfp:"SFP", -c_full:"全双工",c_half:"半双工",c_devices:"台设备",c_yes:"是",c_no:"否", +c_full:"全双工",c_half:"半双工",c_yes:"是",c_no:"否", d_ports:"端口",d_ports_h:"点击端口查看详情",d_system:"系统",d_traffic:"流量", d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误", i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件", @@ -263,7 +263,7 @@ i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"S p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误", p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率", p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力", -pt_title:"端口配置",pt_conn:"已连接设备",pt_speed:"速率",pt_mtu:"MTU", +pt_title:"端口配置",pt_conn:"已学习设备",pt_speed:"速率",pt_mtu:"MTU", pt_sfp_note:"SFP 速率按插槽设置,不会保存到启动配置。", pt_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383", stp_title:"生成树",stp_h:"RSTP, 802.1w",stp_version:"版本",stp_v_stp:"STP 兼容", @@ -368,7 +368,7 @@ th_sel_light:"Selenized claro",th_sel_dark:"Selenized oscuro", c_port:"Puerto",c_name:"Nombre",c_link:"Enlace",c_apply:"Aplicar",c_cancel:"Cancelar",c_confirm:"Confirmar", c_close:"Cerrar",c_refresh:"Actualizar",c_off:"apagado",c_offc:"Apagado",c_down:"caído",c_on:"Encendido",c_auto:"Auto",c_delete:"Eliminar", c_type:"Tipo",c_state:"Estado",c_enabled:"Habilitado",c_load:"Cargar",c_disable:"Deshabilitar",c_sfp:"SFP", -c_full:"dúplex completo",c_half:"semidúplex",c_devices:"dispositivos",c_yes:"sí",c_no:"no", +c_full:"dúplex completo",c_half:"semidúplex",c_yes:"sí",c_no:"no", d_ports:"Puertos",d_ports_h:"pulsa un puerto para ver detalles",d_system:"Sistema",d_traffic:"Tráfico", d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos", i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware", @@ -376,7 +376,7 @@ i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog", p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos", p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX", p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado", -pt_title:"Configuración de puerto",pt_conn:"Conectado",pt_speed:"Velocidad",pt_mtu:"MTU", +pt_title:"Configuración de puerto",pt_conn:"Dispositivos aprendidos",pt_speed:"Velocidad",pt_mtu:"MTU", pt_sfp_note:"La velocidad del SFP se ajusta por ranura y no se guarda en la configuración de inicio.", pt_name_err:"Nombre de puerto: 1-15 caracteres, sin espacios",pt_mtu_err:"El MTU debe estar entre 64 y 16383", stp_title:"Árbol de expansión",stp_h:"RSTP, 802.1w",stp_version:"Versión",stp_v_stp:"STP compatible", @@ -480,7 +480,7 @@ th_sel_light:"Clair (sélénisé)",th_sel_dark:"Sombre (sélénisé)", c_port:"Port",c_name:"Nom",c_link:"Lien",c_apply:"Appliquer",c_cancel:"Annuler",c_confirm:"Confirmer", c_close:"Fermer",c_refresh:"Raffraichir",c_off:"arrêt",c_offc:"Arrêt",c_down:"arrêt",c_on:"Marche",c_auto:"Auto",c_delete:"Supprimer", c_type:"Type",c_state:"Etat",c_enabled:"Activé",c_load:"Charger",c_disable:"Désactivé",c_sfp:"SFP", -c_full:"full",c_half:"half",c_devices:"Equipements",c_yes:"oui",c_no:"non", +c_full:"full",c_half:"half",c_yes:"oui",c_no:"non", d_ports:"Ports",d_ports_h:"Cliquez ou survollez pour plus de détails",d_system:"Système",d_traffic:"Trafic", d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO", i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel", @@ -488,7 +488,7 @@ i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Fla p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais", p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance", p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités", -pt_title:"Configuration du port",pt_conn:"Connecté à",pt_speed:"Vitesse",pt_mtu:"MTU", +pt_title:"Configuration du port",pt_conn:"Appareils appris",pt_speed:"Vitesse",pt_mtu:"MTU", pt_sfp_note:"La vitesse SFP est paramétrée pour le port et n'est pas enregistrée dans la configuration de démarrage.", pt_name_err:"Nom du port: 1 à 15 caractères, sans espaces",pt_mtu_err:"MTU doit être comrpis entre 64 et 16383", stp_title:"Arborescence",stp_h:"RSTP, 802.1w",stp_version:"Protocole",stp_v_stp:"Compatible STP", @@ -597,7 +597,7 @@ th_sel_light:"Selenized Hell",th_sel_dark:"Selenized Dunkel", c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Übernehmen",c_cancel:"Abbrechen",c_confirm:"Bestätigen", c_close:"Schliessen",c_refresh:"Aktualisieren",c_off:"aus",c_offc:"Aus",c_down:"getrennt",c_on:"Ein",c_auto:"Auto",c_delete:"Löschen", c_type:"Typ",c_state:"Zustand",c_enabled:"Aktiviert",c_load:"Laden",c_disable:"Deaktivieren",c_sfp:"SFP", -c_full:"voll",c_half:"halb",c_devices:"Geräte",c_yes:"ja",c_no:"nein", +c_full:"voll",c_half:"halb",c_yes:"ja",c_no:"nein", d_ports:"Ports",d_ports_h:"Port anklicken für Details",d_system:"System",d_traffic:"Datenverkehr", d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft", i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware", @@ -605,7 +605,7 @@ i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog: p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft", p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung", p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten", -pt_title:"Port-Konfiguration",pt_conn:"Verbunden",pt_speed:"Geschwindigkeit",pt_mtu:"MTU", +pt_title:"Port-Konfiguration",pt_conn:"Gelernte Geräte",pt_speed:"Geschwindigkeit",pt_mtu:"MTU", pt_sfp_note:"Die SFP-Geschwindigkeit wird pro Steckplatz gesetzt und nicht in der Startkonfiguration gespeichert.", pt_name_err:"Port-Name: 1-15 Zeichen, keine Leerzeichen",pt_mtu_err:"MTU muss zwischen 64 und 16383 liegen", stp_title:"Spanning Tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP-kompatibel", @@ -1153,31 +1153,12 @@ function loadMtu(){ }); }); } -/* One learned MAC is the attached device; several means a switch or AP - * sits behind the port, so only the count is shown. */ -function portsMacs(){ - l2Load().then(function(all){ - var by={}; - all.forEach(function(e){ - if(e.pport==="CPU")return; - var l=by[e.pport]=by[e.pport]||[]; - if(l.indexOf(e.mac)<0)l.push(e.mac); - }); - S.ports.forEach(function(p){ - var el=$("pmac"+(p.portNum-1)); - if(!el)return; - var m=by[p.portNum]||[]; - el.textContent=!m.length?"-":(m.length===1?m[0]:m.length+" "+t("c_devices")); - el.title=m.join("\n"); - }); - }).catch(function(){}); -} -var _macTick=0; function portsStatus(){ buildPorts(); - if(++_macTick%10===0)portsMacs(); S.ports.forEach(function(p){ var i=p.portNum-1,el=$("plink"+i); + var mc=$("pmac"+i); + if(mc)mc.textContent=parseInt(p.macs,16)&0x1fff; if(el)el.innerHTML=linkBadge(p); var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)]; if(sel&&v&&document.activeElement!==sel)sel.value=v; @@ -1205,8 +1186,8 @@ function applyPort(i){ postCmds(cmds).then(loadMtu).catch(function(){}); } tabHooks.ports={ - enter:function(){statusPoller.start();needPorts(function(){buildPorts();portsMacs()})}, - leave:function(){statusPoller.stop();l2Gen++}, + enter:function(){statusPoller.start();needPorts(buildPorts)}, + leave:function(){statusPoller.stop()}, status:portsStatus, }; diff --git a/html/index.html b/html/index.html index 21b7d17f..9b14660b 100644 --- a/html/index.html +++ b/html/index.html @@ -237,7 +237,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}

Port configuration

- +
PortNameLinkConnectedSpeedEnabledMTU
PortNameLinkDevices learnedSpeedEnabledMTU

SFP speed is set per slot and is not saved in the startup config.

diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 183510d0..006d2dbe 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -1111,6 +1111,9 @@ void send_status(void) slen += strtox(outbuf + slen, "\",\"rxB\":\"0x"); STAT_GET(STAT_COUNTER_ERR_PKTS, i); reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors + + slen += strtox(outbuf + slen, "\",\"macs\":\"0x"); + reg_to_html(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2)); slen += strtox(outbuf + slen, "\"}"); if (i < machine.max_port) char_to_html(','); diff --git a/rtl837x_port.c b/rtl837x_port.c index e3600eba..f82fc713 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -510,7 +510,7 @@ void port_media_show(uint8_t port) __banked void port_stats_print(void) __banked { - print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); + print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\t\tMACs\n"); for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { print_phys_port(i); write_char('\t'); @@ -584,6 +584,9 @@ void port_stats_print(void) __banked STAT_GET(STAT_COUNTER_ERR_PKTS, i); print_reg(RTL837X_STAT_V_HIGH); write_char('\t'); + + reg_read(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2)); + itoa_short(SFR_DATA_U16 & L2_LRN_PORT_CNT_MASK); print_string("\n"); } } diff --git a/rtl837x_regs.h b/rtl837x_regs.h index c2117fb1..93eb7f44 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -214,6 +214,8 @@ #define RTL837x_L2_TBL_FLUSH_CNF 0x53dc #define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384 #define RTL837X_L2_LRN_PORT_CONSTRT_ACT 0x4f80 +#define RTL837X_L2_LRN_PORT_CONSTRT_CNT 0x53ac +#define L2_LRN_PORT_CNT_MASK 0x1fff #define RTL8373_REG_MAC_L2_PORT_MAX_LEN 0x1250 /* diff --git a/test/test_page_json.c b/test/test_page_json.c index e650a538..a7626565 100644 --- a/test/test_page_json.c +++ b/test/test_page_json.c @@ -185,6 +185,23 @@ static void t_l2_page(void) CHECK(balanced(), "every page is valid JSON"); } +static void t_status_macs(void) +{ + const char *p1, *end, *mac; + + printf("[test] /status.json reports the MAC addresses learned on each port\n"); + hw_reset(); out_reset(); + hw_reg_set(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (1 << 2), 0x21); + send_status(); + p1 = strstr(body(), "\"logPort\":1,"); + end = p1 ? strchr(p1, '}') : NULL; + mac = p1 ? strstr(p1, "\"macs\":\"0x21\"") : NULL; + CHECK(mac && mac < end, "port 1 shows its learned count"); + CHECK(has("\"macs\":\"0x0\""), "a port without learned addresses shows 0"); + CHECK(slen <= TCP_OUTBUF_SIZE, "fits the buffer"); + CHECK(balanced(), "valid JSON"); +} + static void t_status_counters(void) { printf("[test] /status.json prints 64-bit packet counters in full\n"); @@ -211,6 +228,7 @@ int main(void) t_l2(); t_l2_page(); t_status_counters(); + t_status_macs(); printf("\n%d checks, %d failed\n", tests_run, tests_failed); return tests_failed ? 1 : 0; } diff --git a/tools/httpd_sim.c b/tools/httpd_sim.c index 5fea029f..68f87232 100644 --- a/tools/httpd_sim.c +++ b/tools/httpd_sim.c @@ -56,6 +56,7 @@ time_t last_session_use; uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS]; char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20]; +char macs_buff[8]; char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6]; char num_buff[20]; char l2_idx_buff[20]; @@ -180,6 +181,12 @@ void send_status(int s) json_object_object_add(v, "txB", json_object_new_string(txB_buff)); json_object_object_add(v, "rxG", json_object_new_string(rxG_buff)); json_object_object_add(v, "rxB", json_object_new_string(rxB_buff)); + uint16_t macs = 0; + for (int e = 0; e < L2_ENTRY_NUM; e++) + if (l2_entries[e].port == physToLogPort[i-1] && l2_entries[e].type != 's') + macs++; + sprintf(macs_buff, "0x%04x", macs); + json_object_object_add(v, "macs", json_object_new_string(macs_buff)); if (i >= PORTS - NSFP) { uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100); uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100);