Understanding Data Center Fabrics - Part 6: BGP Underlay
Mục lục
- 1. Vì sao layer quan trọng: aggregation, summarization và abstraction
- 2. Module, black box và interaction surface
- 3. Vertical layering: mô hình RINA
- 4. Áp dụng vào data center fabric: horizontal vs vertical layering
- 5. Vì sao nhiều người chọn BGP cho underlay
- 6. Single-protocol fabric: iBGP cho underlay, eBGP cho overlay
- 7. Vấn đề: BGP hội tụ rất chậm
- 8. Cách tăng tốc hội tụ — và cái giá phải trả
- 9. Những vấn đề vận hành khác khi dùng BGP làm underlay
1. Vì sao layer quan trọng: aggregation, summarization và abstraction
Trong một thiết kế mạng phân cấp truyền thống (access – distribution – core, hoặc hai lớp aggregation – core), điều thực sự tách các layer này ra khỏi nhau chính là aggregation và summarization — hay nói cách khác là abstraction: rút bớt, loại bỏ thông tin ra khỏi hệ thống.
Việc này giúp chứa (contain) failure domain — hay "blast radius": nếu một liên kết ở dưới thay đổi, và có aggregation ở lớp trên, thì các router core không cần biết về sự kiện đó.
Cơ chế đứng sau điều này không có gì huyền bí — nó nằm ở việc recomputation bị chặn lại đúng chỗ. Nếu không có summarization, mỗi router giữ route chi tiết tới từng prefix cụ thể; khi một liên kết bên dưới flap, mọi router trên đường truyền route đó phải chạy lại best-path (hoặc SPF, với link-state), rồi tiếp tục advertise thay đổi lên router phía trên — sự kiện nhỏ lan truyền qua toàn bộ chuỗi phân cấp. Khi có summarization, router thực hiện gộp route (ví dụ core chỉ thấy 10.1.0.0/16 thay vì 256 route /24) sẽ tự hấp thụ sự kiện đó trong nội bộ: nó có thể tự chọn lại đường đi bên trong khối được gộp, nhưng miễn là khối đó vẫn còn reachable tổng thể, route summary advertise lên trên hoàn toàn không đổi — router phía trên không có gì để recompute cả. Đó chính là cơ chế cụ thể của việc "chứa blast radius": aggregation biến một thay đổi topology thành no-op ở mọi layer nằm phía trên điểm gộp route.
💡 Hình dung như thế này: giống một công ty nhiều cấp quản lý — nhân viên tuyến đầu báo cáo chi tiết từng sự cố nhỏ (đơn hàng trễ, khách phàn nàn) lên quản lý trực tiếp, nhưng quản lý trực tiếp chỉ tổng hợp thành một dòng báo cáo ngắn gọn ("doanh số tuần này đạt 95% mục tiêu") gửi lên cấp giám đốc. Giám đốc không cần biết chi tiết từng sự cố nhỏ — miễn tổng thể vẫn ổn, không có gì phải "tính toán lại" ở cấp của họ. Đó chính là cách summarization chứa blast radius: sự cố nhỏ được hấp thụ ở đúng cấp nó xảy ra, không lan lên toàn bộ chuỗi quản lý phía trên.
2. Module, black box và interaction surface
Trong kiểu thiết kế này, mỗi phần (ví dụ lớp aggregation) có thể coi là một module. Mục tiêu là làm cho các module càng lặp lại (repeatable) càng tốt — chỉ thiết kế một module một lần, giúp tiết kiệm thời gian và dễ troubleshoot vì các module đều giống nhau.
Nơi các module tiếp xúc nhau gọi là interaction surface. Mỗi module có thể coi như một black box — khi nhìn tổng thể hệ thống, không nhất thiết phải biết chi tiết bên trong mỗi module (dù vẫn cần biết khi cần). Độ phức tạp được giấu bên trong mỗi block, nhưng đồng thời cũng phát sinh thêm phức tạp tại các interaction surface khi ghép các module lại với nhau.
Đây chính là ý tưởng đằng sau state-optimization-surface trade-off triad: aggregation làm giảm state, nhưng gần như luôn kéo theo giảm optimization (ví dụ traffic đi theo đường không tối ưu). Mục tiêu thiết kế là chia layer đúng chỗ để kiểm soát độ phức tạp — nếu layer sai chỗ, độ phức tạp thực ra sẽ tăng lên thay vì giảm.
💡 Ví dụ cụ thể cho dễ hình dung: khi router core chỉ nhận một route summary
10.1.0.0/16thay vì 256 route/24chi tiết bên dưới, nó tiết kiệm được rất nhiều state (ít route hơn trong bảng định tuyến, ít CPU/RAM hơn để xử lý, ít churn hơn khi có sự cố cục bộ). Nhưng cái giá phải trả là core không còn biết chính xác10.1.5.0/24đang nằm ở nhánh nào bên dưới — nếu có 2 đường đi khả dụng tới hai nhánh khác nhau nhưng route đã bị gộp lại, traffic có thể bị đẩy tới nhánh xa hơn thay vì nhánh gần nhất, tức là đi non-optimal path. Đó chính là trade-off: đổi state lấy optimization, và interaction surface (điểm router core "nhìn thấy" summary thay vì chi tiết) chính là nơi đánh đổi này xảy ra.
Vì sao "lặp lại" (repeatable) lại quan trọng đến vậy?
Thiết kế một module để nó lặp lại được không phải vì đẹp trên giấy, mà vì nó khấu hao (amortize) chi phí kỹ sư: nếu module A được thiết kế, kiểm thử và viết runbook troubleshooting đúng một lần, rồi nhân bản ra N lần trong toàn hệ thống, chi phí thiết kế chỉ trả một lần nhưng lợi ích nhân lên N lần — mọi kỹ sư vận hành chỉ cần học đúng một mẫu hình. Ngược lại, nếu mỗi module hơi khác nhau một chút (khác số lượng uplink, khác cách đặt VLAN, khác policy), người vận hành phải nhớ N biến thể khác nhau, và độ phức tạp vận hành tăng theo, thậm chí nhanh hơn, số biến thể đó — đây chính là lý do các nhà thiết kế fabric lớn luôn cố "đóng khuôn" một pod/module rồi nhân bản, thay vì tự do tùy biến từng cụm.
Nhưng black box không miễn phí. Mọi chi tiết bị giấu bên trong module sẽ, sớm hay muộn, "rò rỉ" ra ngoài qua đúng interaction surface — hiện tượng này thường được gọi là leaky abstraction. Ví dụ: nếu bên trong module aggregation dùng jumbo frame (MTU lớn hơn 1500 byte) cho traffic đông bộ nội bộ, còn module hàng xóm chỉ hỗ trợ MTU mặc định, thì về nguyên tắc module aggregation "không cần" biết chi tiết bên trong module hàng xóm — nhưng trên thực tế vẫn phải biết, nếu không traffic vượt MTU sẽ bị drop hoặc fragment ngay tại interaction surface. Độ phức tạp bị giấu bên trong module không biến mất, nó chỉ chuyển chỗ, dồn hết về đúng nơi các module chạm nhau.
3. Vertical layering: mô hình RINA
Một ví dụ khác về layering là mô hình RINA — viết tắt của Recursive InterNetwork Architecture, do John Day đề xuất trong cuốn sách "Patterns in Network Architecture" (2008). Ý tưởng: nghĩ về cách layer hóa transport theo chiều dọc — mỗi layer đều có marshalling and multiplexing, và error and flow control — nhưng khác nhau về phạm vi: layer interface-to-interface (tương ứng Ethernet), layer host-to-host (tương ứng IP), và layer app-to-app (ví dụ HTML).
Nói dễ hiểu hơn: thay vì mỗi tầng trong mạng có một bộ giao thức hoàn toàn khác nhau tùy theo chức năng (Ethernet làm việc A, IP làm việc B, TCP làm việc C), RINA đề xuất dùng lặp lại cùng một bộ chức năng (marshalling/multiplexing, error/flow control) ở nhiều phạm vi (scope) khác nhau — từ hẹp nhất (giữa hai interface vật lý) tới rộng nhất (giữa hai ứng dụng). Đây là lý do mô hình này gọi là "recursive" — cùng một pattern được lặp lại đệ quy ở các tầng scope khác nhau, thay vì mỗi tầng có logic riêng biệt.
DIF và IPC Process: hai khái niệm cốt lõi của RINA
Để hiểu "layer" trong RINA nghĩa là gì cụ thể, cần hai khái niệm: DIF (Distributed IPC Facility) và IPC Process (IPCP). Một DIF chính là một layer — một "network" hoàn chỉnh trong đúng phạm vi của nó, gồm nhiều IPC Process cùng cộng tác để cung cấp dịch vụ truyền dữ liệu (IPC — Inter-Process Communication) cho các ứng dụng phía trên. Mỗi IPC Process trong một DIF thực hiện đúng 2 nhóm chức năng lặp lại ở mọi layer: marshalling và multiplexing (đóng gói dữ liệu ứng dụng thành đơn vị truyền, ghép nhiều luồng lên chung một kênh), và error and flow control (phát hiện lỗi, đảm bảo tin cậy, điều tiết tốc độ gửi cho khớp khả năng nhận).
Điểm khiến RINA thực sự "recursive": ứng dụng nằm phía trên một DIF (gọi là Application Process — AP) hoàn toàn có thể chính là một IPC Process của DIF ở tầng cao hơn kế tiếp. Nói cách khác, "ứng dụng" và "layer" không phải hai khái niệm tách biệt cố định như trong mô hình OSI 7 tầng — chúng là cùng một pattern, chỉ khác ở việc đang đứng ở góc nhìn scope nào. Nhìn từ trên xuống, IP là một DIF hoàn chỉnh phục vụ TCP; nhưng nhìn từ góc TCP trở lên, IP chỉ đóng vai trò một AP cung cấp dịch vụ IPC cho DIF ứng dụng nằm phía trên nó. Chính vì layer nào cũng dùng chung một khuôn (cùng 2 nhóm chức năng, chỉ khác scope), RINA không cần thiết kế một giao thức mới mỗi khi cần thêm một tầng — chỉ cần khởi tạo thêm một DIF mới ở scope tương ứng.
💡 Hình dung như thế này: RINA giống một bộ búp bê Nga (matryoshka) — mở con búp bê ngoài cùng ra, bên trong lại là một con búp bê y hệt về hình dáng, chỉ nhỏ hơn. Layer app-to-app, layer host-to-host, layer interface-to-interface đều là "cùng một con búp bê" — cùng làm marshalling/multiplexing và error/flow control — chỉ khác nhau ở "kích thước" phạm vi hoạt động. Khác với mô hình OSI, nơi mỗi tầng gần như là một loại búp bê hoàn toàn riêng (tầng transport khác hẳn tầng network về chức năng), RINA chỉ có đúng một khuôn búp bê, lặp lại đệ quy từ trong ra ngoài.
4. Áp dụng vào data center fabric: horizontal vs vertical layering
Thay vì chỉ layer theo chiều ngang (hierarchical — access/aggregation/core), có thể layer theo chiều dọc ngay bên trong một module — ví dụ layer aggregation có thể tự nó gồm 3-4 layer con bên trong. Lợi ích: cho phép xây module lớn hơn và phẳng hơn, vì interaction surface giờ được xây theo chiều dọc thay vì trải dài theo chiều ngang của toàn topology — giúp kiểm soát độ phức tạp ngay trong phạm vi một module.
Áp dụng vào data center fabric: có thể xây fabric với nhiều layer control plane khác nhau — underlay control plane, overlay control plane, và có thể thêm layer orchestration/controller/intent-based ở trên cùng. Ví dụ với hệ thống intent-based: có một intent layer với controller quản lý cấu hình của overlay, và overlay lại là một layer tách biệt với underlay — giữa mỗi layer là một interaction surface. Đây chính là cách áp dụng vertical layering (thay vì horizontal layering) vào bên trong một thiết kế mạng phân cấp, giúp xây module lớn hơn, phẳng hơn và kiểm soát độ phức tạp theo một cách khác.
Vì sao "phẳng hơn" lại là lợi ích cụ thể, không chỉ là mỹ từ? Trong horizontal layering, số lượng interaction surface tỷ lệ thuận với số cạnh giữa các module cạnh nhau trong topology: access nói chuyện với aggregation, aggregation nói chuyện với core, mỗi cặp cạnh nhau là một interaction surface riêng, và số cặp này tăng theo chiều ngang khi mạng phình to (thêm rack, thêm pod). Trong vertical layering, interaction surface không còn nằm giữa các module cạnh nhau theo topology nữa, mà nằm giữa các control plane xếp chồng bên trong cùng một module, nên số lượng interaction surface không phụ thuộc vào việc mạng có bao nhiêu leaf/pod theo chiều ngang — nó chỉ phụ thuộc vào số layer control plane xếp chồng, vốn thường cố định (2-3 layer, dù fabric có 10 hay 500 leaf switch). Đây là lý do vertical layering scale tốt hơn khi mạng phình to: thêm 100 leaf switch không sinh thêm interaction surface nào cả, vì mỗi leaf mới vẫn chỉ mang đúng chừng đó layer control plane bên trong nó — controller ở layer intent chỉ cần nói chuyện với layer overlay qua đúng một interaction surface duy nhất, bất kể fabric có bao nhiêu leaf.
5. Vì sao nhiều người chọn BGP cho underlay
Quay lại câu hỏi layering ở trên: nếu underlay control plane chỉ là một trong các layer xếp chồng theo chiều dọc, thì chọn giao thức nào cho layer đó? Trong thực tế, BGP là giao thức mà đa số người nghĩ tới đầu tiên khi nói về control plane cho data center fabric — dù BGP vốn không được thiết kế cho việc này, mà được thiết kế để kết nối các autonomous system (AS) với nhau. Về bản chất, BGP là một policy language đặt trên nền một thuật toán routing loop-free — không phải shortest-path-first thuần túy mà là policy-path-first: có một cơ chế shortest-path-first nhưng chỉ đóng vai trò tiebreaker — AS path không phải là công cụ chính để đảm bảo loop-free, mà độ dài đường đi ngắn nhất chỉ được dùng khi không có policy nào khác ghi đè; việc loại bỏ loop thực chất dựa vào việc phát hiện lặp trong AS path.
Theo RFC 7938, các lý do phổ biến khiến người ta chọn BGP cho fabric gồm:
- Prefix distribution — OSPF và IS-IS cũng làm được, không có gì khác biệt.
- Prefix filtering — OSPF/IS-IS là link-state protocol nên không hỗ trợ filtering nhiều; BGP là path-vector protocol nên hỗ trợ filtering rất mạnh với nhiều loại policy.
- Traffic tagging — cơ bản đến mở rộng.
- Multi-vendor stability — hầu như mọi vendor đều implement BGP tốt.
- Simple implementation, ease of operational support.
- Minimize the failure domain — đây là điểm mạnh tự nhiên của path-vector protocol: path vector tự động tóm tắt (summarize) thông tin topology tại mỗi hop, nên tự thân giao thức đã có tính module hóa.
Lưu ý quan trọng: bản chất cả ba điểm prefix distribution/filtering/tagging đều xoay quanh policy, không phải shortest-path — chính vì BGP tập trung mạnh vào policy nên nó hữu ích trong các trường hợp cần áp policy phức tạp.
Cơ chế "policy trước, shortest-path sau" hoạt động thế nào
Best-path selection process của BGP là một chuỗi bước so sánh có thứ tự, dừng lại ngay khi có bước nào phân định được người thắng. Thứ tự phổ biến (theo cách Cisco triển khai, các vendor khác gần tương tự): weight (cục bộ, không advertise) → local preference → route tự originate → độ dài AS path → origin type → MED → ưu tiên eBGP hơn iBGP → IGP metric tới next-hop → router ID. Nhìn vào thứ tự này sẽ thấy rõ tại sao BGP được gọi là "policy-path-first": hai attribute đứng đầu tiên — weight và local preference — đều là policy thuần túy, do người vận hành cấu hình tùy ý, hoàn toàn không liên quan đến việc đường nào ngắn hơn. Độ dài AS path chỉ được xét đến ở bước thứ tư, sau khi mọi policy đã được áp dụng hết và vẫn chưa phân định được — đúng như tên gọi "tiebreaker": nó chỉ có tiếng nói khi không còn tiêu chí policy nào khác để dựa vào.
Cơ chế loop-free của BGP cũng tách biệt khỏi việc chọn shortest-path: mỗi khi một route được advertise ra khỏi một AS, AS đó tự thêm ASN của mình vào đầu AS_PATH; nếu một router nhận được route mà AS_PATH đã chứa sẵn ASN của chính nó, nó biết chắc route này đã đi vòng qua chính mình và loại bỏ ngay — không cần biết đường đi đó dài hay ngắn. Đây chính là ý nghĩa của khẳng định "AS path không phải công cụ chính để đảm bảo loop-free" — việc phát hiện vòng lặp dựa vào so khớp ASN trong AS_PATH, còn độ dài AS_PATH chỉ được dùng sau đó, như một tiêu chí xếp hạng giữa các đường hợp lệ.
RFC 7938 cụ thể hóa điều này thành một sơ đồ cấp phát ASN cho Clos fabric: toàn bộ router Tier 1 (spine) dùng chung một ASN duy nhất; mỗi cụm (cluster) Tier 2 dùng một ASN riêng; và mỗi thiết bị Tier 3 (ToR/leaf) dùng một ASN riêng cho chính nó. Sơ đồ này không chỉ để "có số cho vui" — nó trực tiếp kiểm soát hiện tượng BGP path hunting: khi một leaf nhận được route quảng bá lại có AS_PATH đã chứa ASN của chính nó (vì route đó đi vòng qua một leaf khác rồi vòng lại), cơ chế loop detection tiêu chuẩn sẽ tự động loại route đó, ngăn traffic đi lòng vòng giữa các leaf với nhau — hai leaf không bao giờ trở thành transit của nhau.
6. Single-protocol fabric: iBGP cho underlay, eBGP cho overlay
Một cách tiếp cận phổ biến là xây single-protocol fabric — dùng BGP cho cả underlay lẫn overlay: chạy iBGP để mang route của underlay, và eBGP để mang route của overlay. Cách này có vẻ đơn giản hóa mọi thứ: chỉ một giao thục để cấu hình/quản lý, chỉ một protocol để troubleshoot, và cùng một bộ công cụ policy dùng được cho cả underlay lẫn overlay (dù vẫn có một số khác biệt nhỏ giữa iBGP và eBGP về cách tính best-path, nhưng có thể xử lý được).
Vì sao lại chia việc như vậy thay vì dùng cùng một loại session cho cả hai? Underlay chỉ cần đúng một việc: cho mọi loopback trong fabric biết đường tới nhau — không cần AS_PATH policy phức tạp, không cần phân biệt tenant. Gom toàn bộ underlay vào một AS duy nhất và chạy iBGP phù hợp với mục tiêu đó: route học được không bị AS_PATH dài ra qua từng hop, và vì mọi thiết bị đứng chung một AS, không có rủi ro route bị loop-detect nhầm. Cái giá phải trả là iBGP có một ràng buộc mặc định: một router không tự động re-advertise route học từ một iBGP peer sang một iBGP peer khác (nguyên tắc chống loop nội bộ AS, vì iBGP không có AS_PATH để tự phát hiện vòng lặp như eBGP) — nên bắt buộc phải có full mesh giữa mọi router, hoặc dùng route reflector (RR) ở spine để tránh phải mesh toàn bộ N² session.
Ngược lại, overlay cần mang thông tin có tính "chính sách" hơn nhiều: route EVPN của từng tenant, cần khả năng gắn community, prepend AS_PATH, hoặc chặn route lan sang nhánh không liên quan — đúng thế mạnh của eBGP. Cấp một AS riêng cho từng leaf (đúng tinh thần sơ đồ ASN của RFC 7938 nói ở mục 5) khiến overlay session giữa các leaf trở thành eBGP thực sự, tận dụng được toàn bộ bộ công cụ policy theo AS mà không cần RR — mỗi eBGP session tự nhiên re-advertise cho các peer khác mà không bị ràng buộc "không re-advertise giữa các iBGP peer" như underlay. Next-hop của route overlay (EVPN VTEP) được resolve đệ quy (recursive next-hop resolution) qua chính route underlay bên dưới — đây là điểm nối giữa hai layer: overlay không tự biết cách tới VTEP đích, nó dựa hoàn toàn vào bảng route mà iBGP underlay đã xây sẵn.
💡 Hình dung như thế này: single-protocol fabric giống một công ty chỉ dùng đúng một kênh email cho mọi việc — từ thông báo nội bộ đơn giản (underlay: "link A vừa down") đến quyết định kinh doanh phức tạp (overlay: "khách hàng X cần policy cô lập riêng"). Tiện vì nhân viên chỉ cần thành thạo một công cụ, nhưng dễ lẫn lộn giữa hai loại thông tin có mức độ quan trọng và tốc độ xử lý rất khác nhau — đây chính là cái giá của việc gộp underlay/overlay vào cùng một giao thức, sẽ rõ hơn ở phần 9.
7. Vấn đề: BGP hội tụ rất chậm
Vấn đề đầu tiên khi dùng BGP làm underlay: BGP hội tụ rất chậm.
Ví dụ minh họa: bơm route 1100::/64 vào mạng, tất cả router chạy eBGP, không có policy nào khác ngoài tiebreaker theo độ dài AS path. Sau khi hội tụ, router P có 4 đường đi tới đích: qua G, qua M, qua K, qua N. Khi liên kết giữa A và đích 1100::/64 bị đứt:
- t1: A gửi withdrawal tới G, B, C, D.
- t2: G, B, C, D tính lại best path; G gửi withdrawal tới P, B gửi withdrawal tới M, C gửi tới F, D gửi tới E. P nhận withdrawal từ G, mất best path, chuyển sang đường tốt tiếp theo (qua M).
- t3: M gửi withdrawal, F gửi withdrawal, E gửi withdrawal. P nhận withdrawal từ M, chuyển sang đường qua K.
- t4: K gửi withdrawal, H gửi withdrawal tới N. P nhận withdrawal từ K, chuyển sang đường qua N.
- t5: N gửi withdrawal. P nhận ra không còn đường nào tới đích nữa.
Mỗi khoảng thời gian giữa các bước t này chính xác bằng Min Route Advertisement Interval (MRAI) — MRAI là yếu tố kiểm soát tốc độ hội tụ của BGP trong mạng có nhiều đường đi song song (ECMP cao). Với một mạng dạng butterfly fabric (kể cả loại nhỏ), số hop cần đi qua 5-stage fabric cộng thêm các route phản xạ (reflected path) và multi-hop path khiến đường đi có thể rất dài — điều này làm chậm đáng kể tốc độ hội tụ của BGP, khiến việc hội tụ trong môi trường này trở nên rất khó khăn.
Vì sao MRAI tồn tại, và vì sao nó lại "cắt lát" quá trình hội tụ như vậy
MRAI không phải một lỗi thiết kế — nó được đưa vào BGP để giới hạn tốc độ (rate-limit) số UPDATE message một router gửi cho từng peer về từng prefix, tránh tình trạng một prefix không ổn định (flapping liên tục) làm ngập CPU của toàn bộ router lân cận bằng hàng loạt UPDATE dồn dập. Bộ đếm MRAI áp dụng theo từng cặp (peer, prefix) — nghĩa là mỗi khi best-path cho một prefix thay đổi, router phải đợi đủ MRAI kể từ lần advertise gần nhất cho đúng peer đó, đúng prefix đó rồi mới gửi update tiếp theo, dù entry mới có sẵn sàng ngay lập tức trong bảng định tuyến nội bộ.
Đây chính là lý do bước hội tụ trong ví dụ trên bị "cắt lát" thành nhiều khoảng MRAI liên tiếp: mỗi hop trên đường đi cũ đều phải tự chờ hết MRAI của riêng nó trước khi báo tiếp cho hop kế tiếp — router P không nhận được toàn bộ 4 withdrawal cùng lúc, mà nhận rải rác theo từng đợt MRAI của từng hop upstream, nên phải "dò" lần lượt hết đường dự phòng thứ nhất, thứ hai, thứ ba rồi mới tới đường cuối cùng. Có một điểm tinh tế: bản thân RFC 4271 áp MRAI cho cả announcement lẫn withdrawal, nhưng nhiều triển khai hiện đại (và bản thân draft đề xuất loại bỏ giá trị mặc định cũ) cho phép loại trừ withdrawal ra khỏi MRAI để withdrawal được gửi ngay lập tức — nếu áp dụng đúng cơ chế này, chuỗi hội tụ trong ví dụ trên có thể rút ngắn đáng kể vì các bước withdrawal không còn phải chờ đủ MRAI ở từng hop.
Về giá trị mặc định: RFC 4271 gợi ý MRAI mặc định 30 giây cho eBGP và 5 giây cho iBGP — nghĩa là với ví dụ 4 đường đi ở trên chạy thuần eBGP, tổng thời gian hội tụ lý thuyết có thể lên tới hàng chục giây đến vài phút chỉ vì phải chờ đủ MRAI ở từng hop. Trên thiết bị thực tế, giá trị này đã được nhiều vendor điều chỉnh khác đi so với khuyến nghị gốc của RFC — ví dụ Cisco IOS/IOS-XE mặc định dùng 30 giây cho eBGP nhưng 0 giây cho iBGP (không phải 5 giây như RFC gợi ý). Có thể xem và chỉnh giá trị này trên thiết bị thực tế:
# Cisco IOS-XE — xem và chỉnh advertisement-interval cho một neighbor
router bgp 65001
neighbor 10.0.0.1 advertisement-interval 5
show ip bgp neighbors 10.0.0.1 | include minimum time
# Output minh họa:
# Default minimum time between advertisement runs is 5 seconds
# Juniper JunOS — tương đương là "out-delay" trên neighbor
set protocols bgp group UNDERLAY neighbor 10.0.0.1 out-delay 5
show bgp neighbor 10.0.0.1 | match "Outbound Timer"
# Output minh họa:
# Outbound Timer: 5
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
Giá trị mặc định 30s/5s của RFC 4271 thực tế đã được nhiều vendor hạ xuống thấp hơn nhiều cho kịch bản data center underlay (thường về gần 0), và IETF cũng có draft riêng đề xuất bỏ khuyến nghị mặc định cũ này để linh hoạt hơn — xem ghi chú ở mục Nguồn tham khảo.
8. Cách tăng tốc hội tụ — và cái giá phải trả
Có hai kỹ thuật phổ biến để giúp BGP hội tụ nhanh hơn trong data center fabric:
- Ngăn top-of-rack switch phản xạ (reflect) withdrawal/advertisement ngược trở lên — vì các switch này về nguyên tắc không nên đóng vai trò transit trong BGP. Có thể cấu hình filter kiểu
^$(chỉ cho phép advertise những route có AS path rỗng). Lưu ý: BGP chỉ thêm local AS number sau khi đã advertise, nên filter này thực chất là chỉ dẫn top-of-rack switch: nếu nhận được route từ router phía trên, không re-advertise route đó. - Đặt toàn bộ router ở lớp spine vào cùng một AS — khi đó khi route bị withdraw/advertise theo một hướng, nó sẽ không bị re-advertise ngược trở lại vì được học từ cùng một AS.
Cơ chế phía sau kỹ thuật 1: một top-of-rack switch bình thường nhận route từ nhiều spine, chọn best-path, rồi re-advertise route đó (kèm AS_PATH đã có sẵn nhiều hop) sang các spine còn lại và các leaf lân cận — chính hành vi "học rồi phát lại" này khiến nó vô tình trở thành một điểm trung chuyển (transit), kéo dài chuỗi phụ thuộc hội tụ đã minh họa ở mục 7. Filter ^$ chặn đứng việc này: nó chỉ cho phép advertise ra ngoài những route có AS_PATH rỗng — tức route do chính top-of-rack switch đó originate (ví dụ subnet server cắm trực tiếp vào nó) — còn mọi route học được từ nơi khác (AS_PATH khác rỗng) đều bị chặn không cho advertise tiếp. Kết quả: top-of-rack switch chỉ còn đóng vai trò leaf thuần túy, không transit, nên số hop cần chờ MRAI để hội tụ giảm hẳn.
# FRR (vtysh) trên top-of-rack switch — chỉ advertise route tự originate, chặn transit
bgp as-path access-list ORIGINATED-ONLY seq 5 permit ^$
route-map TOR-NO-TRANSIT permit 10
match as-path ORIGINATED-ONLY
router bgp 65101
neighbor 10.0.0.1 remote-as 65000
neighbor 10.0.0.1 route-map TOR-NO-TRANSIT out
!
show bgp neighbor 10.0.0.1 advertised-routes
# Output minh họa:
# BGP table version is 12, local router ID is 10.0.0.5
# Network Next Hop Metric LocPrf Weight Path
# *> 10.1.5.0/24 0.0.0.0 0 32768 i
# Total number of prefixes 1
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ. Chỉ prefix tự originate — AS_PATH rỗng, ký hiệu i là origin IGP — xuất hiện trong danh sách advertised-routes; mọi route học từ spine với AS_PATH khác rỗng đều bị route-map chặn, không hiện trong output này.)
Kỹ thuật 2 dựa trên đúng nguyên tắc iBGP đã nói ở mục 6: nếu mọi spine đứng chung một AS, một route đi ra từ AS đó rồi có nguy cơ quay lại chính AS đó sẽ bị loop-detection dựa trên AS_PATH loại bỏ ngay từ phía nhận, thay vì phải đợi vài vòng "quảng bá rồi rút lại" mới ổn định — đây chính là cơ chế RFC 7938 gọi là kiểm soát path hunting đã nhắc ở mục 5.
Có nhiều cách khác để giúp BGP hội tụ nhanh hơn, nhưng về bản chất, làm những việc này chính là đang biến BGP thành một phiên bản RIP rất cầu kỳ (fancy RIP) — điều này hoàn toàn hợp lệ và không có gì sai, nếu mục tiêu là làm BGP hội tụ đủ nhanh để dùng làm underlay protocol.
9. Những vấn đề vận hành khác khi dùng BGP làm underlay
Ngoài tốc độ hội tụ, dùng BGP làm underlay còn kéo theo một số vấn đề vận hành khác:
- Phải tính toán hoặc cấu hình router ID và AS number cho từng thiết bị.
- Phải thiết lập peering qua link-local, hoặc cấu hình thủ công/qua hệ thống automation.
- Phải tự động phát hiện (auto discover) các peer cục bộ — đã có nhiều đề xuất tại IETF nhằm giải quyết vấn đề này.
- Router phải chấp nhận peer với bất kỳ ai cố mở kết nối (open peering) — đây là một attack surface: nếu kẻ tấn công xâm nhập được vào mạng, chúng có thể peer với một trong các BGP router của bạn.
- Nếu có controller cần thực hiện traffic steering, phải dùng thêm công cụ như BGP-LS để thu thập topology view của mạng — vì bản thân BGP path-vector không tự cung cấp view topology đầy đủ.
Vì sao "router ID + AS number" lại thành gánh nặng, trong khi IGP không gặp vấn đề này
Cơ chế nằm ở chính bản chất của BGP: đây là giao thức giữa hai bên đã biết trước danh tính của nhau, không phải giao thức tự khám phá hàng xóm như IGP. Với OSPF hay IS-IS, một router chỉ cần bật giao thức trên interface, gửi multicast Hello, và tự động hình thành adjacency với bất kỳ router nào cùng chạy giao thức đó trên cùng segment — không cần gán trước bất kỳ định danh duy nhất nào ngoài router ID (mà bản thân cũng có thể tự chọn theo địa chỉ IP cao nhất). BGP thì ngược lại: mỗi speaker cần một router ID duy nhất (thường lấy từ loopback IPv4) và một AS number duy nhất, và về nguyên tắc cổ điển, mỗi neighbor relationship cần địa chỉ IP của peer được cấu hình tường minh ở cả hai đầu trước khi TCP session có thể hình thành. Đúng theo sơ đồ cấp ASN của RFC 7938 nói ở mục 5 — mỗi leaf một ASN riêng — một hệ thống automation phải tính toán và đẩy xuống một cặp (ASN, router ID) duy nhất cho từng thiết bị, chứ không chỉ cho từng pod hay từng loại module. Đây chính xác là loại state-per-device mà horizontal layering (module hóa, lặp lại một khuôn mẫu — nhắc ở mục 2) vốn muốn tránh.
Vì sao "link-local peering" lại là câu trả lời thực tế cho vấn đề địa chỉ IP
Nếu phải gán một địa chỉ IP point-to-point (ví dụ một subnet /31) cho từng liên kết leaf-spine trong một Clos fabric có hàng trăm liên kết, chi phí quản lý địa chỉ sẽ rất lớn. Giải pháp thực tế mà nhiều triển khai BGP underlay dùng — thường gọi là BGP unnumbered — là dùng địa chỉ IPv6 link-local (tự sinh trên interface qua SLAAC, không cần cấp phát thủ công) làm điểm neo cho session BGP, và tận dụng IPv6 Neighbor Discovery (ND) để tự động phát hiện router kề cạnh ngay khi cáp được cắm — đây chính là ý nghĩa của "peering qua link-local" trong danh sách trên. Vì underlay vẫn cần mang prefix IPv4 (loopback của các thiết bị), cơ chế extended next-hop encoding theo RFC 5549 (được RFC 8950 kế thừa và thay thế) cho phép một NLRI IPv4 được advertise cùng next-hop IPv6 — nhờ đó một session BGP chạy hoàn toàn trên địa chỉ IPv6 link-local vẫn mang được route IPv4 cần thiết cho underlay. Cơ chế này giải quyết được phần "không cần cấp IP thủ công cho từng liên kết", nhưng không giải quyết được gánh nặng "mỗi thiết bị một ASN riêng" đã nói ở trên — ASN của thiết bị vẫn phải được biết trước hoặc cấu hình theo quy ước xác định.
Vì sao "open peering" là attack surface có thật, không chỉ lý thuyết
Để BGP unnumbered thực sự "plug-and-play" — cắm cáp là lên session mà không cần biết trước ASN của switch bên kia — nhiều triển khai cấu hình interface ở chế độ chấp nhận bất kỳ ASN bên ngoài nào peer tới (kiểu cấu hình dynamic/external-any phổ biến trên các nền tảng như FRR/Cumulus phục vụ zero-touch provisioning). Đây chính là nguồn gốc của attack surface: nếu kẻ tấn công có được quyền truy cập lớp 2 vào một liên kết trong fabric (ví dụ một cổng leaf hướng ra server bị xâm nhập, hoặc một thiết bị giả mạo được cắm vào cáp leaf-spine), nó có thể tự mở một BGP session hợp lệ về mặt giao thức và bơm route giả vào underlay — vì route underlay là nền cho việc resolve next-hop của cả overlay (nhắc ở mục 6), một session BGP giả mạo có thể làm traffic bị blackhole hoặc bị chuyển hướng sai. Các biện pháp giảm thiểu phổ biến trong thực tế gồm: chỉ chấp nhận peer thụ động (passive, không bao giờ chủ động mở session), giới hạn TTL theo GTSM (RFC 5082 — chỉ chấp nhận gói có TTL 255, tức chắc chắn đến từ router kề trực tiếp, không phải từ xa qua nhiều hop), giới hạn số prefix nhận vào (prefix-limit), và kiểm soát truy cập vật lý/cổng (port security). Đây là đánh đổi cố hữu của open peering, không phải điều có thể loại bỏ hoàn toàn chỉ bằng cấu hình BGP.
Vì sao cần thêm hẳn BGP-LS cho controller
BGP, với vai trò một path-vector protocol, chỉ advertise best path đã chọn cục bộ tại mỗi hop — nó không mang theo toàn bộ đồ thị topology (những link nào tồn tại giữa những node nào, băng thông, mức sử dụng, TE metric) theo cách một link-state IGP lưu trong LSDB của nó. Một controller làm traffic engineering tập trung (ví dụ né traffic khỏi một liên kết đang nghẽn) cần nhìn thấy toàn bộ đồ thị đó, không chỉ reachability theo từng prefix. RFC 7752 định nghĩa BGP-LS: một mở rộng của BGP cho phép router xuất thông tin link-state cục bộ của nó ra dưới dạng NLRI BGP thông thường, nhờ đó một controller chỉ cần chạy BGP session bình thường (không cần truy cập trực tiếp vào IGP) vẫn có thể dựng lại một Traffic Engineering Database đầy đủ của toàn mạng. (RFC 7752 sau này được RFC 9552, năm 2024, cập nhật/thay thế với cùng mục đích cốt lõi.)
Một vấn đề khác đáng lưu ý: nếu dùng BGP cho cả underlay lẫn overlay, sẽ mất đi sự tách biệt sạch sẽ giữa vertical layering và horizontal layering — vì lúc này vertical layering (underlay/overlay) đang được xây dựng theo cùng cách với horizontal layering, vốn nhằm mục đích kiểm soát độ phức tạp và giúp mạng scale tốt hơn.
Cái giá cụ thể của việc "mất tách biệt" đó
Quay lại khái niệm interaction surface và black box ở mục 2: vertical layering (underlay tách khỏi overlay) chỉ thực sự có giá trị module hóa nếu hai layer đó độc lập được với nhau — thay đổi bên trong layer này không đòi hỏi phải hiểu chi tiết bên trong layer kia. Khi cả hai layer cùng chạy chung một protocol stack (BGP), interaction surface giữa chúng không còn là một ranh giới rõ ràng — nó bị "rò rỉ" (leaky abstraction, nhắc ở mục 2) theo chiều ngược lại: một knob chỉnh timer hoặc policy để xử lý sự cố ở overlay (ví dụ route churn của một tenant cụ thể trong EVPN) hoàn toàn có thể vô tình ảnh hưởng tới hành vi hội tụ của underlay đã phân tích ở mục 7-8, vì đó là cùng một tiến trình BGP, cùng một cơ chế MRAI, cùng một bảng best-path selection xử lý cả hai loại route. Kết quả là troubleshooting một sự cố overlay đôi khi buộc phải suy luận cả về hành vi underlay, và ngược lại — đúng là điều mà việc tách layer ra ban đầu muốn tránh.
Nhìn chung, link-state protocol hội tụ nhanh hơn và cho khả năng quan sát (visibility) tốt hơn trong mạng — vì bản chất link-state IGP tự động phát hiện hàng xóm qua Hello multicast và tự flood toàn bộ topology cho mọi node, không cần cấu hình tường minh ASN/router ID hay địa chỉ peer như BGP. Đây sẽ là nội dung của phần tiếp theo: dùng link state làm underlay thay vì BGP.
Nguồn tham khảo
Nguồn gốc: Understanding Data Center Fabrics, Part 6: BGP Underlay — kênh Packet Pushers
Ghi chú fact-check (đối chiếu RFC gốc, truy cập 2026-07-13):
- Danh sách lý do "theo RFC 7938" trong bài là diễn giải của video (dẫn từ một bảng so sánh bên thứ ba, không trích nguyên văn RFC). Đối chiếu trực tiếp RFC 7938 §5.1 "Choosing EBGP as the Routing Protocol", các lý do chính thức là: (1) đơn giản hơn về cấu trúc dữ liệu/state machine so với link-state IGP; (2) overhead flooding thông tin thấp hơn link-state IGP; (3) hỗ trợ traffic engineering qua third-party/recursively-resolved next-hop; (4) chuẩn hóa đa vendor nhờ cơ chế cấp phát ASN và AS_PATH loop detection; (5) cô lập failure domain tốt hơn nhờ AS_PATH là tiebreaker sớm trong best-path selection; (6) đơn giản hóa vận hành/troubleshooting. Về tinh thần, khá gần với những gì video tóm tắt (đa vendor, đơn giản, cô lập failure domain), nhưng RFC không nhấn mạnh riêng "prefix filtering" như một lý do chính. (RFC 7938)
- MRAI mặc định: RFC 4271 gợi ý 30 giây (eBGP) / 5 giây (iBGP). Giá trị này sau đó bị một draft riêng của IETF (
draft-ietf-idr-mrai-dep) đề xuất deprecate để cho phép triển khai linh hoạt hơn (bao gồm loại trừ withdrawal khỏi MRAI) — nhiều vendor hiện đại đã hạ mặc định xuống thấp hơn nhiều cho kịch bản data center. (IETF draft-ietf-idr-mrai-dep) - RINA (không phải "RHINO"): transcript gốc ghi tên mô hình là "RHINO — Recursive Internet Architecture", nhiều khả năng là lỗi nhận diện giọng nói khi chuyển từ audio sang văn bản (tương tự lỗi "desktop flood" → "Dynamic Flooding" ở Part 08). Đối chiếu nguồn học thuật, tên chuẩn là RINA — Recursive InterNetwork Architecture, do John Day đề xuất trong sách "Patterns in Network Architecture: A Return to Fundamentals" (2008), dựa trên nguyên lý networking-is-IPC và layering theo scope thay vì theo chức năng. Bài đã sửa "RHINO" thành "RINA" trong thân bài (section 3) cho khớp thuật ngữ chuẩn. (Wikipedia — Recursive Internetwork Architecture)