sitesEVPNTopologies := client.SitesEVPNTopologies()
SitesEVPNTopologies
- Create Site Evpn Topology
- Delete Site Evpn Topology
- Get Site Evpn Topology
- List Site Evpn Topologies
- Update Site Evpn Topology
While all the evpn_id
/ downlink_ips
can be specifidd by hand, the easiest way is to call the build_vpn_topology
API, allowing you to examine the diff, and update it yourself. You can also simply call it with overwrite=true
which will apply the updates for you.
Notes:
- You can use
core
/distribution
/access
to create a CLOS topology - You can also use
core
/distribution
to form a 2-tier EVPN topology where ESI-Lag is configured distribution to connect to access switches - In a small/medium campus,
collapsed-core
can be used where core switches are the inter-connected to do EVPN - The API uses a few pre-defined parameters and best-practices to generate the configs. It can be customized by using
evpn_options
in Site Setting / Network Template. (e.g. a different subnet for the underlay)
In a small-medium campus, EVPN can also be enabled only at the core switches (up to 4) by assigning all participating switches with collapsed-core role
. When there are more than 2 switches, a ring-like topology will be formed.
If the access switchess does not have EVPN support, you can take advantage of EVPN by setting up ESI-Lag on distribution switches
For leaf nodes in a EVPN topology, you’d have to configure the IPs for networks that would participate in EVPN. Optionally, VRFs to isolate traffic from one tenant verus another
CreateSiteEvpnTopology(
ctx context.Context,
siteId uuid.UUID,
body *models.EvpnTopology) (
models.ApiResponse[models.EvpnTopology],
error)
Parameter | Type | Tags | Description |
---|---|---|---|
siteId |
uuid.UUID |
Template, Required | - |
body |
*models.EvpnTopology |
Body, Optional | - |
ctx := context.Background()
siteId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
body := models.EvpnTopology{
Name: models.ToPointer("CC"),
Overwrite: models.ToPointer(true),
PodNames: map[string]string{
"1": "default",
"2": "default",
},
Switches: []models.EvpnTopologySwitch{
models.EvpnTopologySwitch{
Mac: "5c5b35000003",
Role: models.EvpnTopologySwitchRoleEnum("collapsed-core"),
},
models.EvpnTopologySwitch{
Mac: "5c5b35000004",
Role: models.EvpnTopologySwitchRoleEnum("collapsed-core"),
},
},
}
apiResponse, err := sitesEVPNTopologies.CreateSiteEvpnTopology(ctx, siteId, &body)
if err != nil {
log.Fatalln(err)
} else {
// Printing the result and response
fmt.Println(apiResponse.Data)
fmt.Println(apiResponse.Response.StatusCode)
}
{
"id": "9197ec96-4c8d-529f-c595-035895e688b2",
"name": "CC",
"overwrite": true,
"pod_names": {
"1": "default",
"2": "default"
},
"switches": [
{
"deviceprofile_id": "6a1deab1-96df-4fa2-8455-d5253f943d06",
"downlink_ips": [
"10.255.240.6",
"10.255.240.8"
],
"downlinks": [
"5c5b35000007",
"5c5b35000008"
],
"esilaglinks": [
"5c5b3500000f"
],
"evpn_id": 1,
"mac": "5c5b35000003",
"model": "QFX10002-36Q",
"role": "collapsed-core",
"site_id": "1916d52a-4a90-11e5-8b45-1258369c38a9",
"uplinks": [
"5c5b35000005",
"5c5b35000006"
]
}
]
}
HTTP Status Code | Error Description | Exception Class |
---|---|---|
400 | Bad Syntax | ResponseHttp400Exception |
401 | Unauthorized | ResponseHttp401ErrorException |
403 | Permission Denied | ResponseHttp403ErrorException |
404 | Not found. The API endpoint doesn’t exist or resource doesn’ t exist | ResponseHttp404Exception |
429 | Too Many Request. The API Token used for the request reached the 5000 API Calls per hour threshold | ResponseHttp429ErrorException |
Delete the site EVPN Topology
DeleteSiteEvpnTopology(
ctx context.Context,
siteId uuid.UUID,
evpnTopologyId uuid.UUID) (
http.Response,
error)
Parameter | Type | Tags | Description |
---|---|---|---|
siteId |
uuid.UUID |
Template, Required | - |
evpnTopologyId |
uuid.UUID |
Template, Required | - |
``
ctx := context.Background()
siteId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
evpnTopologyId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
resp, err := sitesEVPNTopologies.DeleteSiteEvpnTopology(ctx, siteId, evpnTopologyId)
if err != nil {
log.Fatalln(err)
} else {
fmt.Println(resp.StatusCode)
}
HTTP Status Code | Error Description | Exception Class |
---|---|---|
400 | Bad Syntax | ResponseHttp400Exception |
401 | Unauthorized | ResponseHttp401ErrorException |
403 | Permission Denied | ResponseHttp403ErrorException |
404 | Not found. The API endpoint doesn’t exist or resource doesn’ t exist | ResponseHttp404Exception |
429 | Too Many Request. The API Token used for the request reached the 5000 API Calls per hour threshold | ResponseHttp429ErrorException |
Get One EVPN Topology Detail
GetSiteEvpnTopology(
ctx context.Context,
siteId uuid.UUID,
evpnTopologyId uuid.UUID) (
models.ApiResponse[models.EvpnTopology],
error)
Parameter | Type | Tags | Description |
---|---|---|---|
siteId |
uuid.UUID |
Template, Required | - |
evpnTopologyId |
uuid.UUID |
Template, Required | - |
ctx := context.Background()
siteId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
evpnTopologyId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
apiResponse, err := sitesEVPNTopologies.GetSiteEvpnTopology(ctx, siteId, evpnTopologyId)
if err != nil {
log.Fatalln(err)
} else {
// Printing the result and response
fmt.Println(apiResponse.Data)
fmt.Println(apiResponse.Response.StatusCode)
}
{
"id": "9197ec96-4c8d-529f-c595-035895e688b2",
"name": "CC",
"overwrite": true,
"pod_names": {
"1": "default",
"2": "default"
},
"switches": [
{
"deviceprofile_id": "6a1deab1-96df-4fa2-8455-d5253f943d06",
"downlink_ips": [
"10.255.240.6",
"10.255.240.8"
],
"downlinks": [
"5c5b35000007",
"5c5b35000008"
],
"esilaglinks": [
"5c5b3500000f"
],
"evpn_id": 1,
"mac": "5c5b35000003",
"model": "QFX10002-36Q",
"role": "collapsed-core",
"site_id": "1916d52a-4a90-11e5-8b45-1258369c38a9",
"uplinks": [
"5c5b35000005",
"5c5b35000006"
]
}
]
}
HTTP Status Code | Error Description | Exception Class |
---|---|---|
400 | Bad Syntax | ResponseHttp400Exception |
401 | Unauthorized | ResponseHttp401ErrorException |
403 | Permission Denied | ResponseHttp403ErrorException |
404 | Not found. The API endpoint doesn’t exist or resource doesn’ t exist | ResponseHttp404Exception |
429 | Too Many Request. The API Token used for the request reached the 5000 API Calls per hour threshold | ResponseHttp429ErrorException |
Get the existing EVPN topology
ListSiteEvpnTopologies(
ctx context.Context,
siteId uuid.UUID) (
models.ApiResponse[models.EvpnTopology],
error)
Parameter | Type | Tags | Description |
---|---|---|---|
siteId |
uuid.UUID |
Template, Required | - |
ctx := context.Background()
siteId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
apiResponse, err := sitesEVPNTopologies.ListSiteEvpnTopologies(ctx, siteId)
if err != nil {
log.Fatalln(err)
} else {
// Printing the result and response
fmt.Println(apiResponse.Data)
fmt.Println(apiResponse.Response.StatusCode)
}
{
"id": "9197ec96-4c8d-529f-c595-035895e688b2",
"name": "CC",
"overwrite": true,
"pod_names": {
"1": "default",
"2": "default"
},
"switches": [
{
"deviceprofile_id": "6a1deab1-96df-4fa2-8455-d5253f943d06",
"downlink_ips": [
"10.255.240.6",
"10.255.240.8"
],
"downlinks": [
"5c5b35000007",
"5c5b35000008"
],
"esilaglinks": [
"5c5b3500000f"
],
"evpn_id": 1,
"mac": "5c5b35000003",
"model": "QFX10002-36Q",
"role": "collapsed-core",
"site_id": "1916d52a-4a90-11e5-8b45-1258369c38a9",
"uplinks": [
"5c5b35000005",
"5c5b35000006"
]
}
]
}
HTTP Status Code | Error Description | Exception Class |
---|---|---|
400 | Bad Syntax | ResponseHttp400Exception |
401 | Unauthorized | ResponseHttp401ErrorException |
403 | Permission Denied | ResponseHttp403ErrorException |
404 | Not found. The API endpoint doesn’t exist or resource doesn’ t exist | ResponseHttp404Exception |
429 | Too Many Request. The API Token used for the request reached the 5000 API Calls per hour threshold | ResponseHttp429ErrorException |
Update the EVPN Topolgy
UpdateSiteEvpnTopology(
ctx context.Context,
siteId uuid.UUID,
evpnTopologyId uuid.UUID,
body *models.EvpnTopology) (
models.ApiResponse[models.EvpnTopology],
error)
Parameter | Type | Tags | Description |
---|---|---|---|
siteId |
uuid.UUID |
Template, Required | - |
evpnTopologyId |
uuid.UUID |
Template, Required | - |
body |
*models.EvpnTopology |
Body, Optional | - |
ctx := context.Background()
siteId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
evpnTopologyId := uuid.MustParse("000000ab-00ab-00ab-00ab-0000000000ab")
body := models.EvpnTopology{
Overwrite: models.ToPointer(false),
Switches: []models.EvpnTopologySwitch{
models.EvpnTopologySwitch{
Mac: "5c5b35000003",
Role: models.EvpnTopologySwitchRoleEnum("collapsed-core"),
},
models.EvpnTopologySwitch{
Mac: "5c5b35000004",
Role: models.EvpnTopologySwitchRoleEnum("none"),
},
},
}
apiResponse, err := sitesEVPNTopologies.UpdateSiteEvpnTopology(ctx, siteId, evpnTopologyId, &body)
if err != nil {
log.Fatalln(err)
} else {
// Printing the result and response
fmt.Println(apiResponse.Data)
fmt.Println(apiResponse.Response.StatusCode)
}
{
"id": "9197ec96-4c8d-529f-c595-035895e688b2",
"name": "CC",
"overwrite": true,
"pod_names": {
"1": "default",
"2": "default"
},
"switches": [
{
"deviceprofile_id": "6a1deab1-96df-4fa2-8455-d5253f943d06",
"downlink_ips": [
"10.255.240.6",
"10.255.240.8"
],
"downlinks": [
"5c5b35000007",
"5c5b35000008"
],
"esilaglinks": [
"5c5b3500000f"
],
"evpn_id": 1,
"mac": "5c5b35000003",
"model": "QFX10002-36Q",
"role": "collapsed-core",
"site_id": "1916d52a-4a90-11e5-8b45-1258369c38a9",
"uplinks": [
"5c5b35000005",
"5c5b35000006"
]
}
]
}
HTTP Status Code | Error Description | Exception Class |
---|---|---|
400 | Bad Syntax | ResponseHttp400Exception |
401 | Unauthorized | ResponseHttp401ErrorException |
403 | Permission Denied | ResponseHttp403ErrorException |
404 | Not found. The API endpoint doesn’t exist or resource doesn’ t exist | ResponseHttp404Exception |
429 | Too Many Request. The API Token used for the request reached the 5000 API Calls per hour threshold | ResponseHttp429ErrorException |