Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ECMP calculator tool #12482

Merged
merged 18 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions platform/mellanox/docker-syncd-mlnx/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ RUN apt-get update && \
python3-pip \
python3-dev \
python-is-python3 \
python3-jsonschema \
{%- if ENABLE_ASAN == "y" %}
libasan6 \
{%- endif %}
Expand Down Expand Up @@ -70,4 +71,10 @@ RUN mkdir -p /etc/supervisor/conf.d/
RUN sonic-cfggen -a "{\"ENABLE_ASAN\":\"{{ENABLE_ASAN}}\"}" -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf
RUN rm -f /usr/share/sonic/templates/supervisord.conf.j2

RUN mkdir -p /usr/bin/ecmp_calculator
COPY ["ecmp_calculator/ecmp_calc_sdk.py", "/usr/bin/ecmp_calculator"]
COPY ["ecmp_calculator/ecmp_calc.py", "/usr/bin/ecmp_calculator"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from ecmp_calc.py other files are not binaries but libraries.Can we package them accordingly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

COPY ["ecmp_calculator/packet_scheme.py", "/usr/bin/ecmp_calculator"]
COPY ["lib/port_utils.py", "/usr/bin/ecmp_calculator"]

ENTRYPOINT ["/usr/local/bin/supervisord"]
133 changes: 133 additions & 0 deletions platform/mellanox/docker-syncd-mlnx/ecmp_calculator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# SONiC ECMP Calculator

## Description
An equal cost multipath (ECMP) is formed when routing table contains multiple next hop addresses for the same destination IP address.
ECMP will load balance the outbound traffic between the IP interfaces.
The purpose of ECMP calculator is to calculate which IP interface ECMP will choose and return the physical interface packet will egress from.
Packet is defined by a JSON file given as an argument to the tool.

## Usage notes
1. ECMP calculator performs its calculations based on the current operational state of the router. In order to calculate the egress port, it fetches routes from HW. Routes exist in HW only for next hops with a resolved ARP.
2. ECMP calculator supports only routed packets.
- IPv4/IPv6 TCP/UDP packets
- IPinIP and VXLAN encapsulated packets
3. Changes done in the packet classification (e.g. ACL, PBR) are not taken into consideration during calculation.

## Command line interface
1. User shall enter syncd container to run ECMP calculator.
2. User shall provide the following input parameters:
- JSON file describing a packet
- Ingress port (e.g. "Ethernet0", must pe a physical interface)
- Debug option for debug purposes (optional)
- VRF name (optional)
3. Usage example:
```
$ docker exec -it syncd bash
$ /usr/bin/ecmp_calculator/ecmp_calc.py -i Ethernet0 -p ./packet.json
Egress port: Ethernet4
```

## Packet JSON
1. Numbers in packet JSON must be in base-ten.
2. For packets with single header, outer header shall be provided.
3. The following table defines the structure of a packet JSON file.

| ecmp_hash | | | | | | |
|-----------|-------------|-------|-------------|-------------|--------|----------------------------------------------------------------------------------|
| | packet_info | | | | object | |
| | | outer | | | object | |
| | | | layer2 | | object | |
| | | | | smac | string | |
| | | | | dmac | string | |
| | | | | ethertype | number | 16bits, needed for IPv4 or IPv6 packet |
| | | | | outer_vid | number | 12bits |
| | | | | outer_pcp | number | 3bits |
| | | | | outer_dei | number | 1bits |
| | | | | inner_vid | number | QinQ |
| | | | | inner_pcp | number | QinQ |
| | | | | inner_dei | number | QinQ |
| | | | ipv4 | | object | |
| | | | | sip | string | |
| | | | | dip | string | |
| | | | | proto | number | 8bits |
| | | | | dscp | number | 6bits |
| | | | | ecn | number | 2bits |
| | | | | mflag | number | 1bit |
| | | | | l3_length | number | 16bits |
| | | | ipv6 | | object | should not co-exist with ipv4 field |
| | | | | sip | string | |
| | | | | dip | string | |
| | | | | mflag | number | 1bit |
| | | | | next_header | number | 8bits |
| | | | | dscp | number | 6bits |
| | | | | ecn | number | 2bits |
| | | | | l3_length | number | 16bits |
| | | | | flow_label | number | 20bits |
| | | | tcp_udp | | object | |
| | | | | sport | number | 16bits |
| | | | | dport | number | 16bits |
| | | | vxlan_nvgre | | object | |
| | | | | vni | number | 24bits |
| | | inner | | | object | overlay |
| | | | layer2 | | object | |
| | | | | smac | string | |
| | | | | dmac | string | |
| | | | | ethertype | number | 16bits |
| | | | ipv4 | | object | |
| | | | | sip | string | |
| | | | | dip | string | |
| | | | | mflag | number | 1bit |
| | | | | proto | number | 8bits |
| | | | ipv6 | | object | should not co-exist with ipv4 field |
| | | | | sip | string | |
| | | | | dip | string | |
| | | | | mflag | number | 1bit |
| | | | | next_header | number | 8bits |
| | | | | flow_label | number | 20bits |
| | | | tcp_udp | | object | |
| | | | | sport | number | 16bits |
| | | | | dport | number | 16bits |

4. Packet JSON file example

```json
{
"packet_info": {
"outer": {
"ipv4": {
"sip": "10.10.10.10",
"dip": "3.3.3.3",
"proto": 17
},
"layer2": {
"smac": "24:8a:07:1e:82:ed",
"dmac": "1c:34:da:1c:a1:00",
"ethertype": 2048
},
"tcp_udp": {
"sport": 100,
"dport": 4789
},
"vxlan_nvgre": {
"vni": 100
}
},
"inner": {
"layer2": {
"smac": "11:11:11:11:11:11",
"dmac": "22:22:22:22:22:22",
"ethertype": 2048
},
"ipv4": {
"sip": "1.1.1.1",
"dip": "2.2.2.3",
"proto": 17,
"mflag": 0
},
"tcp_udp": {
"sport": 100,
"dport": 200
}
}
}
}
Loading