mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-11-27 16:01:20 +01:00
parent
b479f25d5b
commit
c10a61555e
275
Gopkg.lock
generated
275
Gopkg.lock
generated
@ -2,30 +2,39 @@
|
|||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:bf42be3cb1519bf8018dfd99720b1005ee028d947124cab3ccf965da59381df6"
|
||||||
name = "github.com/Microsoft/go-winio"
|
name = "github.com/Microsoft/go-winio"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
||||||
version = "v0.4.7"
|
version = "v0.4.7"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:d1665c44bd5db19aaee18d1b6233c99b0b9a986e8bccb24ef54747547a48027f"
|
||||||
name = "github.com/PuerkitoBio/purell"
|
name = "github.com/PuerkitoBio/purell"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
|
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:c739832d67eb1e9cc478a19cc1a1ccd78df0397bf8a32978b759152e205f644b"
|
||||||
name = "github.com/PuerkitoBio/urlesc"
|
name = "github.com/PuerkitoBio/urlesc"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
|
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:9fd3a6ab34bb103ba228eefd044d3f9aa476237ea95a46d12e8cccd3abf3fea2"
|
||||||
name = "github.com/armon/go-radix"
|
name = "github.com/armon/go-radix"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61"
|
revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:220c8689d516e36f763897aaee8db751f30cbc7f2b87536e44555019796ef191"
|
||||||
name = "github.com/aws/aws-sdk-go"
|
name = "github.com/aws/aws-sdk-go"
|
||||||
packages = [
|
packages = [
|
||||||
"aws",
|
"aws",
|
||||||
@ -54,18 +63,22 @@
|
|||||||
"private/protocol/rest",
|
"private/protocol/rest",
|
||||||
"private/protocol/xml/xmlutil",
|
"private/protocol/xml/xmlutil",
|
||||||
"service/ec2",
|
"service/ec2",
|
||||||
"service/sts"
|
"service/sts",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "9b0098a71f6d4d473a26ec8ad3c2feaac6eb1da6"
|
revision = "9b0098a71f6d4d473a26ec8ad3c2feaac6eb1da6"
|
||||||
version = "v1.13.32"
|
version = "v1.13.32"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
|
||||||
name = "github.com/beorn7/perks"
|
name = "github.com/beorn7/perks"
|
||||||
packages = ["quantile"]
|
packages = ["quantile"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:23cd6ae7715a846f8f0580e89158b9d15f95b0b2dfeae2d612123ed6df31c47a"
|
||||||
name = "github.com/containernetworking/cni"
|
name = "github.com/containernetworking/cni"
|
||||||
packages = [
|
packages = [
|
||||||
"libcni",
|
"libcni",
|
||||||
@ -78,39 +91,49 @@
|
|||||||
"pkg/utils/hwaddr",
|
"pkg/utils/hwaddr",
|
||||||
"pkg/version",
|
"pkg/version",
|
||||||
"plugins/ipam/host-local/backend",
|
"plugins/ipam/host-local/backend",
|
||||||
"plugins/ipam/host-local/backend/allocator"
|
"plugins/ipam/host-local/backend/allocator",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "137b4975ecab6e1f0c24c1e3c228a50a3cfba75e"
|
revision = "137b4975ecab6e1f0c24c1e3c228a50a3cfba75e"
|
||||||
version = "v0.5.2"
|
version = "v0.5.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:df4af3a8e15cd72b068b8d898598001935edce4eac4eb5a3d7fd906036123ff4"
|
||||||
name = "github.com/coreos/go-iptables"
|
name = "github.com/coreos/go-iptables"
|
||||||
packages = ["iptables"]
|
packages = ["iptables"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "259c8e6a4275d497442c721fa52204d7a58bde8b"
|
revision = "259c8e6a4275d497442c721fa52204d7a58bde8b"
|
||||||
version = "v0.2.0"
|
version = "v0.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39"
|
||||||
name = "github.com/davecgh/go-spew"
|
name = "github.com/davecgh/go-spew"
|
||||||
packages = ["spew"]
|
packages = ["spew"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:8583eab935e3d99d3a7ac489cd2ee7c8e95eecd7c64ab1fc8382746dacaf8563"
|
||||||
name = "github.com/dgryski/go-farm"
|
name = "github.com/dgryski/go-farm"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "2de33835d10275975374b37b2dcfd22c9020a1f5"
|
revision = "2de33835d10275975374b37b2dcfd22c9020a1f5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:4189ee6a3844f555124d9d2656fe7af02fca961c2a9bad9074789df13a0c62e0"
|
||||||
name = "github.com/docker/distribution"
|
name = "github.com/docker/distribution"
|
||||||
packages = [
|
packages = [
|
||||||
"digestset",
|
"digestset",
|
||||||
"reference"
|
"reference",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "1e2f10eb65743fed02f573d31a4587de09afb20e"
|
revision = "1e2f10eb65743fed02f573d31a4587de09afb20e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:d40cef2b20331a3a337ff6872f39c470ed5cd4800919f0ef4847403b3df3b172"
|
||||||
name = "github.com/docker/docker"
|
name = "github.com/docker/docker"
|
||||||
packages = [
|
packages = [
|
||||||
"api",
|
"api",
|
||||||
@ -129,169 +152,215 @@
|
|||||||
"api/types/time",
|
"api/types/time",
|
||||||
"api/types/versions",
|
"api/types/versions",
|
||||||
"api/types/volume",
|
"api/types/volume",
|
||||||
"client"
|
"client",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "5c2e6064a1c5cb816081958e5a7079bc6b474940"
|
revision = "5c2e6064a1c5cb816081958e5a7079bc6b474940"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:b6b5c3e8da0fb8073cd2886ba249a40f4402b4391ca6eba905a142cceea97a12"
|
||||||
name = "github.com/docker/go-connections"
|
name = "github.com/docker/go-connections"
|
||||||
packages = [
|
packages = [
|
||||||
"nat",
|
"nat",
|
||||||
"sockets",
|
"sockets",
|
||||||
"tlsconfig"
|
"tlsconfig",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:6f82cacd0af5921e99bf3f46748705239b36489464f4529a1589bc895764fb18"
|
||||||
name = "github.com/docker/go-units"
|
name = "github.com/docker/go-units"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
|
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
|
||||||
version = "v0.3.3"
|
version = "v0.3.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:6b20706ea25f78700bfd6eda620a95233c6340acb53d295553e290c626c809c7"
|
||||||
name = "github.com/docker/libnetwork"
|
name = "github.com/docker/libnetwork"
|
||||||
packages = ["ipvs"]
|
packages = ["ipvs"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "14aa49f99093e1a22e65155b641103762911db8d"
|
revision = "14aa49f99093e1a22e65155b641103762911db8d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:975a4480c40f2d0b95e1f83d3ec1aa29a2774e80179e08a9a4ba2aab86721b23"
|
||||||
name = "github.com/eapache/channels"
|
name = "github.com/eapache/channels"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "47238d5aae8c0fefd518ef2bee46290909cf8263"
|
revision = "47238d5aae8c0fefd518ef2bee46290909cf8263"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:444b82bfe35c83bbcaf84e310fb81a1f9ece03edfed586483c869e2c046aef69"
|
||||||
name = "github.com/eapache/queue"
|
name = "github.com/eapache/queue"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98"
|
revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:d91a89491d49259e41fb09c3a3d42f740d84edee064d8ecede0d64b388bfad71"
|
||||||
name = "github.com/emicklei/go-restful"
|
name = "github.com/emicklei/go-restful"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"log"
|
"log",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "26b41036311f2da8242db402557a0dbd09dc83da"
|
revision = "26b41036311f2da8242db402557a0dbd09dc83da"
|
||||||
version = "v2.6.0"
|
version = "v2.6.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:ddab18e89cf46e40707b89dbe3835b4a591b0ea298e1035eefa84002aa9a4b4e"
|
||||||
name = "github.com/emicklei/go-restful-swagger12"
|
name = "github.com/emicklei/go-restful-swagger12"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "dcef7f55730566d41eae5db10e7d6981829720f6"
|
revision = "dcef7f55730566d41eae5db10e7d6981829720f6"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
|
||||||
name = "github.com/fsnotify/fsnotify"
|
name = "github.com/fsnotify/fsnotify"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
||||||
version = "v1.4.7"
|
version = "v1.4.7"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda"
|
||||||
name = "github.com/ghodss/yaml"
|
name = "github.com/ghodss/yaml"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:ad12727c184fc7e33768f5fe239d8f767a3b60264541067ac2f23b9aca013e06"
|
||||||
name = "github.com/go-ini/ini"
|
name = "github.com/go-ini/ini"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "ace140f73450505f33e8b8418216792275ae82a7"
|
revision = "ace140f73450505f33e8b8418216792275ae82a7"
|
||||||
version = "v1.35.0"
|
version = "v1.35.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:2997679181d901ac8aaf4330d11138ecf3974c6d3334995ff36f20cbd597daf8"
|
||||||
name = "github.com/go-openapi/jsonpointer"
|
name = "github.com/go-openapi/jsonpointer"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
|
revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:1ae3f233d75a731b164ca9feafd8ed646cbedf1784095876ed6988ce8aa88b1f"
|
||||||
name = "github.com/go-openapi/jsonreference"
|
name = "github.com/go-openapi/jsonreference"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
|
revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:5ef2c99a4cac00088f7092ec23f33aadef74ef59b75be43d08a0c9f119bac073"
|
||||||
name = "github.com/go-openapi/spec"
|
name = "github.com/go-openapi/spec"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "370d9e047557906322be8396e77cb0376be6cb96"
|
revision = "370d9e047557906322be8396e77cb0376be6cb96"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:ec7e31653be60f0add6fb60bdc91c21056b9e7bc870cfdcea18ebc45e4dfd916"
|
||||||
name = "github.com/go-openapi/swag"
|
name = "github.com/go-openapi/swag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5"
|
revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a7534feda0f15b5fd691e59e4fb6b7547e27df4b415a62e02c7cb71b3439c1b1"
|
||||||
name = "github.com/gogo/protobuf"
|
name = "github.com/gogo/protobuf"
|
||||||
packages = [
|
packages = [
|
||||||
"proto",
|
"proto",
|
||||||
"sortkeys"
|
"sortkeys",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467"
|
||||||
name = "github.com/golang/glog"
|
name = "github.com/golang/glog"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:0f56223de1ca49228034f96a18d3659415404c986426290b9761935f02894755"
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = [
|
packages = [
|
||||||
"proto",
|
"proto",
|
||||||
"ptypes",
|
"ptypes",
|
||||||
"ptypes/any",
|
"ptypes/any",
|
||||||
"ptypes/duration",
|
"ptypes/duration",
|
||||||
"ptypes/timestamp"
|
"ptypes/timestamp",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "e09c5db296004fbe3f74490e84dcd62c3c5ddb1b"
|
revision = "e09c5db296004fbe3f74490e84dcd62c3c5ddb1b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:9887333bbef17574b1db5f9893ea137ac44107235d624408a3ac9e0b98fbb2cb"
|
||||||
name = "github.com/google/btree"
|
name = "github.com/google/btree"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
|
revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:3ee90c0d94da31b442dde97c99635aaafec68d0b8a3c12ee2075c6bdabeec6bb"
|
||||||
name = "github.com/google/gofuzz"
|
name = "github.com/google/gofuzz"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:5e031a35b76ee001fa9ca9d598298054a123d080e00d13a8dafcfc5e3ecd5b58"
|
||||||
name = "github.com/googleapis/gnostic"
|
name = "github.com/googleapis/gnostic"
|
||||||
packages = [
|
packages = [
|
||||||
"OpenAPIv2",
|
"OpenAPIv2",
|
||||||
"compiler",
|
"compiler",
|
||||||
"extensions"
|
"extensions",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
|
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
|
||||||
version = "v0.1.0"
|
version = "v0.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:86c1210529e69d69860f2bb3ee9ccce0b595aa3f9165e7dd1388e5c612915888"
|
||||||
name = "github.com/gregjones/httpcache"
|
name = "github.com/gregjones/httpcache"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"diskcache"
|
"diskcache",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "9cad4c3443a7200dd6400aef47183728de563a38"
|
revision = "9cad4c3443a7200dd6400aef47183728de563a38"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:cf296baa185baae04a9a7004efee8511d08e2f5f51d4cbe5375da89722d681db"
|
||||||
name = "github.com/hashicorp/golang-lru"
|
name = "github.com/hashicorp/golang-lru"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"simplelru"
|
"simplelru",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40"
|
||||||
name = "github.com/hashicorp/hcl"
|
name = "github.com/hashicorp/hcl"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -303,96 +372,124 @@
|
|||||||
"hcl/token",
|
"hcl/token",
|
||||||
"json/parser",
|
"json/parser",
|
||||||
"json/scanner",
|
"json/scanner",
|
||||||
"json/token"
|
"json/token",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
|
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:0778dc7fce1b4669a8bfa7ae506ec1f595b6ab0f8989c1c0d22a8ca1144e9972"
|
||||||
name = "github.com/howeyc/gopass"
|
name = "github.com/howeyc/gopass"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
|
revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:b39dba8363bf11da3cddcc31c5a9c39f17fba8a5317ae0836ea4530bae3b4866"
|
||||||
name = "github.com/imdario/mergo"
|
name = "github.com/imdario/mergo"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c"
|
revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c"
|
||||||
version = "v0.3.4"
|
version = "v0.3.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
|
||||||
name = "github.com/inconshreveable/mousetrap"
|
name = "github.com/inconshreveable/mousetrap"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||||
version = "v1.0"
|
version = "v1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:ce530152667dc8ba823a586c1c81175aff2c4e15500520883a2727d0ed17c6f1"
|
||||||
name = "github.com/influxdata/influxdb"
|
name = "github.com/influxdata/influxdb"
|
||||||
packages = [
|
packages = [
|
||||||
"client/v2",
|
"client/v2",
|
||||||
"models",
|
"models",
|
||||||
"pkg/escape"
|
"pkg/escape",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "02d7d4f043b34ecb4e9b2dbec298c6f9450c2a32"
|
revision = "02d7d4f043b34ecb4e9b2dbec298c6f9450c2a32"
|
||||||
version = "v1.5.2"
|
version = "v1.5.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:e22af8c7518e1eab6f2eab2b7d7558927f816262586cd6ed9f349c97a6c285c4"
|
||||||
name = "github.com/jmespath/go-jmespath"
|
name = "github.com/jmespath/go-jmespath"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "0b12d6b5"
|
revision = "0b12d6b5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:b1d4df033414c1a0d85fa7037b9aaf03746314811c860a95ea2d5fd481cd6c35"
|
||||||
name = "github.com/json-iterator/go"
|
name = "github.com/json-iterator/go"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
|
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:190ff84d9b2ed6589088f178cba8edb4b8ecb334df4572421fb016be1ac20463"
|
||||||
name = "github.com/juju/ratelimit"
|
name = "github.com/juju/ratelimit"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:5149009cc36718234a9ad2896b04b04716808b8d72143b5687c0a15b53132b27"
|
||||||
name = "github.com/magiconair/properties"
|
name = "github.com/magiconair/properties"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c3beff4c2358b44d0493c7dda585e7db7ff28ae6"
|
revision = "c3beff4c2358b44d0493c7dda585e7db7ff28ae6"
|
||||||
version = "v1.7.6"
|
version = "v1.7.6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:ada518b8c338e10e0afa443d84671476d3bd1d926e13713938088e8ddbee1a3e"
|
||||||
name = "github.com/mailru/easyjson"
|
name = "github.com/mailru/easyjson"
|
||||||
packages = [
|
packages = [
|
||||||
"buffer",
|
"buffer",
|
||||||
"jlexer",
|
"jlexer",
|
||||||
"jwriter"
|
"jwriter",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "8b799c424f57fa123fc63a99d6383bc6e4c02578"
|
revision = "8b799c424f57fa123fc63a99d6383bc6e4c02578"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6"
|
||||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||||
packages = ["pbutil"]
|
packages = ["pbutil"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:2514da1e59c0a936d8c1e0fbf5592267a3c5893eb4555ce767bb54d149e9cf6e"
|
||||||
name = "github.com/mitchellh/mapstructure"
|
name = "github.com/mitchellh/mapstructure"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "00c29f56e2386353d58c599509e8dc3801b0d716"
|
revision = "00c29f56e2386353d58c599509e8dc3801b0d716"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
|
||||||
name = "github.com/modern-go/concurrent"
|
name = "github.com/modern-go/concurrent"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
|
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:d711dfcf661439f1ef0b202a02e8a1ff4deac48f26f34253520dcdbecbd7c5f1"
|
||||||
name = "github.com/modern-go/reflect2"
|
name = "github.com/modern-go/reflect2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
|
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:f4cbb10407f60c0263738e7b219b80ba99516aa9da187f44680d5b29360b3c9f"
|
||||||
name = "github.com/onsi/ginkgo"
|
name = "github.com/onsi/ginkgo"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -412,12 +509,14 @@
|
|||||||
"reporters/stenographer",
|
"reporters/stenographer",
|
||||||
"reporters/stenographer/support/go-colorable",
|
"reporters/stenographer/support/go-colorable",
|
||||||
"reporters/stenographer/support/go-isatty",
|
"reporters/stenographer/support/go-isatty",
|
||||||
"types"
|
"types",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "9eda700730cba42af70d53180f9dcce9266bc2bc"
|
revision = "9eda700730cba42af70d53180f9dcce9266bc2bc"
|
||||||
version = "v1.4.0"
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:038734db8a70cdd73d4215081b22236e2aed3e65ca0727f6afd0ed839630e738"
|
||||||
name = "github.com/onsi/gomega"
|
name = "github.com/onsi/gomega"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -431,27 +530,33 @@
|
|||||||
"matchers/support/goraph/edge",
|
"matchers/support/goraph/edge",
|
||||||
"matchers/support/goraph/node",
|
"matchers/support/goraph/node",
|
||||||
"matchers/support/goraph/util",
|
"matchers/support/goraph/util",
|
||||||
"types"
|
"types",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "003f63b7f4cff3fc95357005358af2de0f5fe152"
|
revision = "003f63b7f4cff3fc95357005358af2de0f5fe152"
|
||||||
version = "v1.3.0"
|
version = "v1.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:ee4d4af67d93cc7644157882329023ce9a7bcfce956a079069a9405521c7cc8d"
|
||||||
name = "github.com/opencontainers/go-digest"
|
name = "github.com/opencontainers/go-digest"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
|
revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
|
||||||
version = "v1.0.0-rc1"
|
version = "v1.0.0-rc1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:11db38d694c130c800d0aefb502fb02519e514dc53d9804ce51d1ad25ec27db6"
|
||||||
name = "github.com/opencontainers/image-spec"
|
name = "github.com/opencontainers/image-spec"
|
||||||
packages = [
|
packages = [
|
||||||
"specs-go",
|
"specs-go",
|
||||||
"specs-go/v1"
|
"specs-go/v1",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d60099175f88c47cd379c4738d158884749ed235"
|
revision = "d60099175f88c47cd379c4738d158884749ed235"
|
||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:653b5223cbe73bc57d2fc74881c6d77e67a056b7c886973cff7d9522d7c04eab"
|
||||||
name = "github.com/osrg/gobgp"
|
name = "github.com/osrg/gobgp"
|
||||||
packages = [
|
packages = [
|
||||||
"api",
|
"api",
|
||||||
@ -465,144 +570,184 @@
|
|||||||
"packet/rtr",
|
"packet/rtr",
|
||||||
"server",
|
"server",
|
||||||
"table",
|
"table",
|
||||||
"zebra"
|
"zebra",
|
||||||
]
|
]
|
||||||
revision = "d31262de7d91c81ff979b39950d2d859666dfa3f"
|
pruneopts = "UT"
|
||||||
|
revision = "v1.33"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:7231124c9669dfb54b82ef8b89f2735cf5d5d2529a23c6ac93a8c4b8bbb28b28"
|
||||||
name = "github.com/pelletier/go-toml"
|
name = "github.com/pelletier/go-toml"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
|
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:3bf17a6e6eaa6ad24152148a631d18662f7212e21637c2699bff3369b7f00fa2"
|
||||||
name = "github.com/petar/GoLLRB"
|
name = "github.com/petar/GoLLRB"
|
||||||
packages = ["llrb"]
|
packages = ["llrb"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
|
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:0e7775ebbcf00d8dd28ac663614af924411c868dca3d5aa762af0fae3808d852"
|
||||||
name = "github.com/peterbourgon/diskv"
|
name = "github.com/peterbourgon/diskv"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
|
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
|
||||||
version = "v2.0.1"
|
version = "v2.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
|
||||||
name = "github.com/pkg/errors"
|
name = "github.com/pkg/errors"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||||
version = "v0.8.0"
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
packages = [
|
packages = [
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"prometheus/promhttp"
|
"prometheus/promhttp",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
||||||
version = "v0.8.0"
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b"
|
||||||
name = "github.com/prometheus/client_model"
|
name = "github.com/prometheus/client_model"
|
||||||
packages = ["go"]
|
packages = ["go"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:e469cd65badf7694aeb44874518606d93c1d59e7735d3754ad442782437d3cc3"
|
||||||
name = "github.com/prometheus/common"
|
name = "github.com/prometheus/common"
|
||||||
packages = [
|
packages = [
|
||||||
"expfmt",
|
"expfmt",
|
||||||
"internal/bitbucket.org/ww/goautoneg",
|
"internal/bitbucket.org/ww/goautoneg",
|
||||||
"model"
|
"model",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6"
|
revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:570784e0ddbf67f14087c6d8cfb7b999b9c55e75518a755e88cb202566ea8a17"
|
||||||
name = "github.com/prometheus/procfs"
|
name = "github.com/prometheus/procfs"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"internal/util",
|
"internal/util",
|
||||||
"nfs",
|
"nfs",
|
||||||
"xfs"
|
"xfs",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
|
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:ff6b0586c0621a76832cf783eee58cbb9d9795d2ce8acbc199a4131db11c42a9"
|
||||||
name = "github.com/satori/go.uuid"
|
name = "github.com/satori/go.uuid"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e"
|
revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:9e9193aa51197513b3abcb108970d831fbcf40ef96aa845c4f03276e1fa316d2"
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||||
version = "v1.0.5"
|
version = "v1.0.5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:fe0b7f0c9a5e5511001fe085b0a156b29266012cd984a63e4059a30e84bba03a"
|
||||||
name = "github.com/spf13/afero"
|
name = "github.com/spf13/afero"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"mem"
|
"mem",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "63644898a8da0bc22138abf860edaf5277b6102e"
|
revision = "63644898a8da0bc22138abf860edaf5277b6102e"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f"
|
||||||
name = "github.com/spf13/cast"
|
name = "github.com/spf13/cast"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "8965335b8c7107321228e3e3702cab9832751bac"
|
revision = "8965335b8c7107321228e3e3702cab9832751bac"
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:716ae4d5ab908a88497f3b5dd25a3bc270160481bdf7ce0108c3d648fcd5ddf1"
|
||||||
name = "github.com/spf13/cobra"
|
name = "github.com/spf13/cobra"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "615425954c3b0d9485a7027d4d451fdcdfdee84e"
|
revision = "615425954c3b0d9485a7027d4d451fdcdfdee84e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805"
|
||||||
name = "github.com/spf13/jwalterweatherman"
|
name = "github.com/spf13/jwalterweatherman"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
|
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
|
||||||
name = "github.com/spf13/pflag"
|
name = "github.com/spf13/pflag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
pruneopts = "UT"
|
||||||
version = "v1.0.1"
|
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:356f83655442b41c5ac8b3fcf04f9a8013449906d04f621826629ce2b91b06a3"
|
||||||
name = "github.com/spf13/viper"
|
name = "github.com/spf13/viper"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "8dc2790b029dc41e2b8ff772c63c26adbb1db70d"
|
revision = "8dc2790b029dc41e2b8ff772c63c26adbb1db70d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:2d9d06cb9d46dacfdbb45f8575b39fc0126d083841a29d4fbf8d97708f43107e"
|
||||||
name = "github.com/vishvananda/netlink"
|
name = "github.com/vishvananda/netlink"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"nl"
|
"nl",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "a2ad57a690f3caf3015351d2d6e1c0b95c349752"
|
revision = "a2ad57a690f3caf3015351d2d6e1c0b95c349752"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:02b1d1b48bf853ea2a9bea029ffe54e3fd7804903a0eda9a78191db8984300d2"
|
||||||
name = "github.com/vishvananda/netns"
|
name = "github.com/vishvananda/netns"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "be1fbeda19366dea804f00efff2dd73a1642fdcc"
|
revision = "be1fbeda19366dea804f00efff2dd73a1642fdcc"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ssh/terminal"]
|
packages = ["ssh/terminal"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
|
revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:ee1694164963c184e44f8c675c96a9a0fcaee79f51194f296e937a7f15bee72d"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
"context",
|
"context",
|
||||||
@ -617,20 +762,24 @@
|
|||||||
"internal/timeseries",
|
"internal/timeseries",
|
||||||
"lex/httplex",
|
"lex/httplex",
|
||||||
"proxy",
|
"proxy",
|
||||||
"trace"
|
"trace",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
|
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:4d0a3e91e65c614186d6f0e9a65b7a1c0f80ff233634585c6f8eed728fabf4cb"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = [
|
packages = [
|
||||||
"unix",
|
"unix",
|
||||||
"windows"
|
"windows",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "2281fa97ef7b0c26324634d5a22f04babdac8713"
|
revision = "2281fa97ef7b0c26324634d5a22f04babdac8713"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:bb8277a2ca2bcad6ff7f413b939375924099be908cedd1314baa21ecd08df477"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = [
|
packages = [
|
||||||
"collate",
|
"collate",
|
||||||
@ -659,18 +808,22 @@
|
|||||||
"unicode/cldr",
|
"unicode/cldr",
|
||||||
"unicode/norm",
|
"unicode/norm",
|
||||||
"unicode/rangetable",
|
"unicode/rangetable",
|
||||||
"width"
|
"width",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:cd018653a358d4b743a9d3bee89e825521f2ab2f2ec0770164bf7632d8d73ab7"
|
||||||
name = "google.golang.org/genproto"
|
name = "google.golang.org/genproto"
|
||||||
packages = ["googleapis/rpc/status"]
|
packages = ["googleapis/rpc/status"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200"
|
revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:f47fb9bd1a9173285be23a1a1342e019abddfd787216e7f2c555ddba837e98ce"
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@ -695,31 +848,39 @@
|
|||||||
"stats",
|
"stats",
|
||||||
"status",
|
"status",
|
||||||
"tap",
|
"tap",
|
||||||
"transport"
|
"transport",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d11072e7ca9811b1100b80ca0269ac831f06d024"
|
revision = "d11072e7ca9811b1100b80ca0269ac831f06d024"
|
||||||
version = "v1.11.3"
|
version = "v1.11.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a"
|
||||||
name = "gopkg.in/inf.v0"
|
name = "gopkg.in/inf.v0"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
|
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
|
||||||
version = "v0.9.1"
|
version = "v0.9.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
branch = "v2"
|
||||||
|
digest = "1:5bb148b78468350091db2ffbb2370f35cc6dcd74d9378a31b1c7b86ff7528f08"
|
||||||
name = "gopkg.in/tomb.v2"
|
name = "gopkg.in/tomb.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "d5d1b5820637886def9eef33e03a27a9f166942c"
|
revision = "d5d1b5820637886def9eef33e03a27a9f166942c"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
|
||||||
name = "gopkg.in/yaml.v2"
|
name = "gopkg.in/yaml.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
version = "v2.2.1"
|
version = "v2.2.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "release-1.8"
|
branch = "release-1.8"
|
||||||
|
digest = "1:b7f1356b82d4992df7724d5d6e4ce7b7bbf878002b8a178560a425a0cd30b18c"
|
||||||
name = "k8s.io/api"
|
name = "k8s.io/api"
|
||||||
packages = [
|
packages = [
|
||||||
"admissionregistration/v1alpha1",
|
"admissionregistration/v1alpha1",
|
||||||
@ -745,11 +906,13 @@
|
|||||||
"scheduling/v1alpha1",
|
"scheduling/v1alpha1",
|
||||||
"settings/v1alpha1",
|
"settings/v1alpha1",
|
||||||
"storage/v1",
|
"storage/v1",
|
||||||
"storage/v1beta1"
|
"storage/v1beta1",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3c2a58f9923aeb5d27fa4d91249e45a1460ca3bd"
|
revision = "3c2a58f9923aeb5d27fa4d91249e45a1460ca3bd"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:bfde7b4a64742525d92a21d3b7ed9695ad72e3922fc9263299b7f1b93f674de4"
|
||||||
name = "k8s.io/apimachinery"
|
name = "k8s.io/apimachinery"
|
||||||
packages = [
|
packages = [
|
||||||
"pkg/api/equality",
|
"pkg/api/equality",
|
||||||
@ -791,13 +954,15 @@
|
|||||||
"pkg/util/yaml",
|
"pkg/util/yaml",
|
||||||
"pkg/version",
|
"pkg/version",
|
||||||
"pkg/watch",
|
"pkg/watch",
|
||||||
"third_party/forked/golang/reflect"
|
"third_party/forked/golang/reflect",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "9d38e20d609d27e00d4ec18f7b9db67105a2bde0"
|
revision = "9d38e20d609d27e00d4ec18f7b9db67105a2bde0"
|
||||||
version = "kubernetes-1.8.0-rc.1"
|
version = "kubernetes-1.8.0-rc.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "release-5.0"
|
branch = "release-5.0"
|
||||||
|
digest = "1:591d0813c53cf297e808a2eabcd8bac67da8f92a4a2d1341812397f909618f65"
|
||||||
name = "k8s.io/client-go"
|
name = "k8s.io/client-go"
|
||||||
packages = [
|
packages = [
|
||||||
"discovery",
|
"discovery",
|
||||||
@ -925,19 +1090,61 @@
|
|||||||
"util/cert",
|
"util/cert",
|
||||||
"util/flowcontrol",
|
"util/flowcontrol",
|
||||||
"util/homedir",
|
"util/homedir",
|
||||||
"util/integer"
|
"util/integer",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "45cf21002ef6b0320709b00606e38d89ed750fab"
|
revision = "45cf21002ef6b0320709b00606e38d89ed750fab"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:f60e3ccfe35ad7632217492c6709871d6c84b2ba77219f054f8d0ef7d1b996e2"
|
||||||
name = "k8s.io/kube-openapi"
|
name = "k8s.io/kube-openapi"
|
||||||
packages = ["pkg/common"]
|
packages = ["pkg/common"]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "f442ecb314a3679150c272e2b9713d8deed5955d"
|
revision = "f442ecb314a3679150c272e2b9713d8deed5955d"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "084480bb06f84e536badc385a76b5e179e27caacc83b769fc984bad231429698"
|
input-imports = [
|
||||||
|
"github.com/aws/aws-sdk-go/aws",
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr",
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session",
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2",
|
||||||
|
"github.com/containernetworking/cni/libcni",
|
||||||
|
"github.com/containernetworking/cni/plugins/ipam/host-local/backend/allocator",
|
||||||
|
"github.com/coreos/go-iptables/iptables",
|
||||||
|
"github.com/docker/docker/client",
|
||||||
|
"github.com/docker/libnetwork/ipvs",
|
||||||
|
"github.com/golang/glog",
|
||||||
|
"github.com/onsi/ginkgo",
|
||||||
|
"github.com/onsi/gomega",
|
||||||
|
"github.com/osrg/gobgp/api",
|
||||||
|
"github.com/osrg/gobgp/config",
|
||||||
|
"github.com/osrg/gobgp/gobgp",
|
||||||
|
"github.com/osrg/gobgp/packet/bgp",
|
||||||
|
"github.com/osrg/gobgp/server",
|
||||||
|
"github.com/osrg/gobgp/table",
|
||||||
|
"github.com/prometheus/client_golang/prometheus",
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp",
|
||||||
|
"github.com/spf13/pflag",
|
||||||
|
"github.com/vishvananda/netlink",
|
||||||
|
"github.com/vishvananda/netns",
|
||||||
|
"golang.org/x/net/context",
|
||||||
|
"k8s.io/api/core/v1",
|
||||||
|
"k8s.io/api/extensions/v1beta1",
|
||||||
|
"k8s.io/api/networking/v1",
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
|
"k8s.io/apimachinery/pkg/labels",
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets",
|
||||||
|
"k8s.io/client-go/informers",
|
||||||
|
"k8s.io/client-go/kubernetes",
|
||||||
|
"k8s.io/client-go/kubernetes/fake",
|
||||||
|
"k8s.io/client-go/listers/core/v1",
|
||||||
|
"k8s.io/client-go/rest",
|
||||||
|
"k8s.io/client-go/tools/cache",
|
||||||
|
"k8s.io/client-go/tools/clientcmd",
|
||||||
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|||||||
@ -57,7 +57,7 @@ required = ["github.com/osrg/gobgp/gobgp"]
|
|||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/osrg/gobgp"
|
name = "github.com/osrg/gobgp"
|
||||||
revision = "d31262de7d91c81ff979b39950d2d859666dfa3f"
|
revision = "v1.33"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
|
|||||||
1334
vendor/github.com/osrg/gobgp/api/attribute.go
generated
vendored
Normal file
1334
vendor/github.com/osrg/gobgp/api/attribute.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2086
vendor/github.com/osrg/gobgp/api/attribute.pb.go
generated
vendored
Normal file
2086
vendor/github.com/osrg/gobgp/api/attribute.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
504
vendor/github.com/osrg/gobgp/api/attribute.proto
generated
vendored
Normal file
504
vendor/github.com/osrg/gobgp/api/attribute.proto
generated
vendored
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation files
|
||||||
|
// (the "Software"), to deal in the Software without restriction,
|
||||||
|
// including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
// and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/any.proto";
|
||||||
|
|
||||||
|
package gobgpapi;
|
||||||
|
|
||||||
|
message OriginAttribute {
|
||||||
|
uint32 origin = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AsSegment {
|
||||||
|
uint32 type = 1;
|
||||||
|
repeated uint32 numbers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AsPathAttribute {
|
||||||
|
repeated AsSegment segments = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NextHopAttribute {
|
||||||
|
string next_hop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiExitDiscAttribute {
|
||||||
|
uint32 med = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LocalPrefAttribute {
|
||||||
|
uint32 local_pref = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AtomicAggregateAttribute {
|
||||||
|
}
|
||||||
|
|
||||||
|
message AggregatorAttribute {
|
||||||
|
uint32 as = 2;
|
||||||
|
string address = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommunitiesAttribute {
|
||||||
|
repeated uint32 communities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OriginatorIdAttribute {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClusterListAttribute {
|
||||||
|
repeated string ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddressPrefix represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=1
|
||||||
|
// - AFI=2, SAFI=1
|
||||||
|
message IPAddressPrefix {
|
||||||
|
uint32 prefix_len = 1;
|
||||||
|
string prefix = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabeledIPAddressPrefix represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=4
|
||||||
|
// - AFI=2, SAFI=4
|
||||||
|
message LabeledIPAddressPrefix {
|
||||||
|
repeated uint32 labels = 1;
|
||||||
|
uint32 prefix_len = 2;
|
||||||
|
string prefix = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncapsulationNLRI represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=7
|
||||||
|
// - AFI=2, SAFI=7
|
||||||
|
message EncapsulationNLRI {
|
||||||
|
string address = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouteDistinguisherTwoOctetAS {
|
||||||
|
uint32 admin = 1;
|
||||||
|
uint32 assigned = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouteDistinguisherIPAddress {
|
||||||
|
string admin = 1;
|
||||||
|
uint32 assigned = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouteDistinguisherFourOctetAS {
|
||||||
|
uint32 admin = 1;
|
||||||
|
uint32 assigned = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EthernetSegmentIdentifier {
|
||||||
|
uint32 type = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVPNEthernetAutoDiscoveryRoute represents the NLRI for:
|
||||||
|
// - AFI=25, SAFI=70, RouteType=1
|
||||||
|
message EVPNEthernetAutoDiscoveryRoute {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
EthernetSegmentIdentifier esi = 2;
|
||||||
|
uint32 ethernet_tag = 3;
|
||||||
|
uint32 label = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVPNMACIPAdvertisementRoute represents the NLRI for:
|
||||||
|
// - AFI=25, SAFI=70, RouteType=2
|
||||||
|
message EVPNMACIPAdvertisementRoute {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
EthernetSegmentIdentifier esi = 2;
|
||||||
|
uint32 ethernet_tag = 3;
|
||||||
|
string mac_address = 4;
|
||||||
|
string ip_address = 5;
|
||||||
|
repeated uint32 labels = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVPNInclusiveMulticastEthernetTagRoute represents the NLRI for:
|
||||||
|
// - AFI=25, SAFI=70, RouteType=3
|
||||||
|
message EVPNInclusiveMulticastEthernetTagRoute {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
uint32 ethernet_tag = 2;
|
||||||
|
string ip_address = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVPNEthernetSegmentRoute represents the NLRI for:
|
||||||
|
// - AFI=25, SAFI=70, RouteType=4
|
||||||
|
message EVPNEthernetSegmentRoute {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
EthernetSegmentIdentifier esi = 2;
|
||||||
|
string ip_address = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVPNIPPrefixRoute represents the NLRI for:
|
||||||
|
// - AFI=25, SAFI=70, RouteType=5
|
||||||
|
message EVPNIPPrefixRoute {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
EthernetSegmentIdentifier esi = 2;
|
||||||
|
uint32 ethernet_tag = 3;
|
||||||
|
string ip_prefix = 4;
|
||||||
|
uint32 ip_prefix_len = 5;
|
||||||
|
string gw_address = 6;
|
||||||
|
uint32 label = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabeledVPNIPAddressPrefix represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=128
|
||||||
|
// - AFI=2, SAFI=128
|
||||||
|
message LabeledVPNIPAddressPrefix {
|
||||||
|
repeated uint32 labels = 1;
|
||||||
|
// One of:
|
||||||
|
// - TwoOctetAsSpecificExtended
|
||||||
|
// - IPv4AddressSpecificExtended
|
||||||
|
// - FourOctetAsSpecificExtended
|
||||||
|
google.protobuf.Any rd = 2;
|
||||||
|
uint32 prefix_len = 3;
|
||||||
|
string prefix = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RouteTargetMembershipNLRI represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=132
|
||||||
|
message RouteTargetMembershipNLRI {
|
||||||
|
uint32 as = 1;
|
||||||
|
// One of:
|
||||||
|
// - TwoOctetAsSpecificExtended
|
||||||
|
// - IPv4AddressSpecificExtended
|
||||||
|
// - FourOctetAsSpecificExtended
|
||||||
|
google.protobuf.Any rt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowSpecIPPrefix {
|
||||||
|
uint32 type = 1;
|
||||||
|
uint32 prefix_len = 2;
|
||||||
|
string prefix = 3;
|
||||||
|
// IPv6 only
|
||||||
|
uint32 offset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowSpecMAC {
|
||||||
|
uint32 type = 1;
|
||||||
|
string address = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowSpecComponentItem {
|
||||||
|
// Operator for Numeric type, Operand for Bitmask type
|
||||||
|
uint32 op = 1;
|
||||||
|
uint64 value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowSpecComponent {
|
||||||
|
uint32 type = 1;
|
||||||
|
repeated FlowSpecComponentItem items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlowSpecNLRI represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=133
|
||||||
|
// - AFI=2, SAFI=133
|
||||||
|
message FlowSpecNLRI {
|
||||||
|
// One of:
|
||||||
|
// - FlowSpecIPPrefix
|
||||||
|
// - FlowSpecMAC
|
||||||
|
// - FlowSpecComponent
|
||||||
|
repeated google.protobuf.Any rules = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VPNFlowSpecNLRI represents the NLRI for:
|
||||||
|
// - AFI=1, SAFI=134
|
||||||
|
// - AFI=2, SAFI=134
|
||||||
|
// - AFI=25, SAFI=134
|
||||||
|
message VPNFlowSpecNLRI {
|
||||||
|
// One of:
|
||||||
|
// - RouteDistinguisherTwoOctetAS
|
||||||
|
// - RouteDistinguisherIPAddressAS
|
||||||
|
// - RouteDistinguisherFourOctetAS
|
||||||
|
google.protobuf.Any rd = 1;
|
||||||
|
// One of:
|
||||||
|
// - FlowSpecIPPrefix
|
||||||
|
// - FlowSpecMAC
|
||||||
|
// - FlowSpecComponent
|
||||||
|
repeated google.protobuf.Any rules = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpaqueNLRI represents the NLRI for:
|
||||||
|
// - AFI=16397, SAFI=241
|
||||||
|
message OpaqueNLRI {
|
||||||
|
bytes key = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MpReachNLRIAttribute {
|
||||||
|
uint32 family = 1;
|
||||||
|
repeated string next_hops = 2;
|
||||||
|
// Each NLRI must be one of:
|
||||||
|
// - IPAddressPrefix
|
||||||
|
// - LabeledIPAddressPrefix
|
||||||
|
// - EncapsulationNLRI
|
||||||
|
// - EVPNEthernetAutoDiscoveryRoute
|
||||||
|
// - EVPNMACIPAdvertisementRoute
|
||||||
|
// - EVPNInclusiveMulticastEthernetTagRoute
|
||||||
|
// - EVPNEthernetSegmentRoute
|
||||||
|
// - EVPNIPPrefixRoute
|
||||||
|
// - LabeledVPNIPAddressPrefix
|
||||||
|
// - RouteTargetMembershipNLRI
|
||||||
|
// - FlowSpecNLRI
|
||||||
|
// - VPNFlowSpecNLRI
|
||||||
|
// - OpaqueNLRI
|
||||||
|
repeated google.protobuf.Any nlris = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MpUnreachNLRIAttribute {
|
||||||
|
uint32 family = 1;
|
||||||
|
// The same as NLRI field of MpReachNLRIAttribute
|
||||||
|
repeated google.protobuf.Any nlris = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TwoOctetAsSpecificExtended {
|
||||||
|
bool is_transitive = 1;
|
||||||
|
uint32 sub_type = 2;
|
||||||
|
uint32 as = 3;
|
||||||
|
uint32 local_admin = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IPv4AddressSpecificExtended {
|
||||||
|
bool is_transitive = 1;
|
||||||
|
uint32 sub_type = 2;
|
||||||
|
string address = 3;
|
||||||
|
uint32 local_admin = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FourOctetAsSpecificExtended {
|
||||||
|
bool is_transitive = 1;
|
||||||
|
uint32 sub_type = 2;
|
||||||
|
uint32 as = 3;
|
||||||
|
uint32 local_admin = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ValidationExtended {
|
||||||
|
uint32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ColorExtended {
|
||||||
|
uint32 color = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EncapExtended {
|
||||||
|
uint32 tunnel_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DefaultGatewayExtended {
|
||||||
|
}
|
||||||
|
|
||||||
|
message OpaqueExtended {
|
||||||
|
bool is_transitive = 1;
|
||||||
|
bytes value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ESILabelExtended {
|
||||||
|
bool is_single_active = 1;
|
||||||
|
uint32 label = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ESImportRouteTarget {
|
||||||
|
string es_import = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MacMobilityExtended {
|
||||||
|
bool is_sticky = 1;
|
||||||
|
uint32 sequence_num = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouterMacExtended {
|
||||||
|
string mac = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrafficRateExtended {
|
||||||
|
uint32 as = 1;
|
||||||
|
float rate = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrafficActionExtended {
|
||||||
|
bool terminal = 1;
|
||||||
|
bool sample = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RedirectTwoOctetAsSpecificExtended {
|
||||||
|
uint32 as = 1;
|
||||||
|
uint32 local_admin = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RedirectIPv4AddressSpecificExtended {
|
||||||
|
string address = 1;
|
||||||
|
uint32 local_admin = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RedirectFourOctetAsSpecificExtended {
|
||||||
|
uint32 as = 1;
|
||||||
|
uint32 local_admin = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrafficRemarkExtended {
|
||||||
|
uint32 dscp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnknownExtended {
|
||||||
|
uint32 type = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtendedCommunitiesAttribute {
|
||||||
|
// Each Community must be one of:
|
||||||
|
// - TwoOctetAsSpecificExtended
|
||||||
|
// - IPv4AddressSpecificExtended
|
||||||
|
// - FourOctetAsSpecificExtended
|
||||||
|
// - OpaqueExtended
|
||||||
|
// - ESILabelExtended
|
||||||
|
// - MacMobilityExtended
|
||||||
|
// - RouterMacExtended
|
||||||
|
// - TrafficRateExtended
|
||||||
|
// - TrafficActionExtended
|
||||||
|
// - RedirectTwoOctetAsSpecificExtended
|
||||||
|
// - RedirectIPv4AddressSpecificExtended
|
||||||
|
// - RedirectFourOctetAsSpecificExtended
|
||||||
|
// - TrafficRemarkExtended
|
||||||
|
// - UnknownExtended
|
||||||
|
repeated google.protobuf.Any communities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message As4PathAttribute {
|
||||||
|
repeated AsSegment segments = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message As4AggregatorAttribute {
|
||||||
|
uint32 as = 2;
|
||||||
|
string address = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PmsiTunnelAttribute {
|
||||||
|
uint32 flags = 1;
|
||||||
|
uint32 type = 2;
|
||||||
|
uint32 label = 3;
|
||||||
|
bytes id = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapSubTLVEncapsulation {
|
||||||
|
uint32 key = 1;
|
||||||
|
bytes cookie = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapSubTLVProtocol {
|
||||||
|
uint32 protocol = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapSubTLVColor {
|
||||||
|
uint32 color = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapSubTLVUnknown {
|
||||||
|
uint32 type = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapTLV {
|
||||||
|
uint32 type = 1;
|
||||||
|
// Each TLV must be one of:
|
||||||
|
// - TunnelEncapSubTLVEncapsulation
|
||||||
|
// - TunnelEncapSubTLVProtocol
|
||||||
|
// - TunnelEncapSubTLVColor
|
||||||
|
// - TunnelEncapSubTLVUnknown
|
||||||
|
repeated google.protobuf.Any tlvs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TunnelEncapAttribute {
|
||||||
|
repeated TunnelEncapTLV tlvs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IPv6AddressSpecificExtended {
|
||||||
|
bool is_transitive = 1;
|
||||||
|
uint32 sub_type = 2;
|
||||||
|
string address = 3;
|
||||||
|
uint32 local_admin = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RedirectIPv6AddressSpecificExtended {
|
||||||
|
string address = 1;
|
||||||
|
uint32 local_admin = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IP6ExtendedCommunitiesAttribute {
|
||||||
|
// Each Community must be one of:
|
||||||
|
// - IPv6AddressSpecificExtended
|
||||||
|
// - RedirectIPv6AddressSpecificExtended
|
||||||
|
repeated google.protobuf.Any communities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AigpTLVIGPMetric {
|
||||||
|
uint64 metric = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AigpTLVUnknown {
|
||||||
|
uint32 type = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AigpAttribute {
|
||||||
|
// Each TLV must be one of:
|
||||||
|
// - AigpTLVIGPMetric
|
||||||
|
// - AigpTLVUnknown
|
||||||
|
repeated google.protobuf.Any tlvs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LargeCommunity {
|
||||||
|
uint32 global_admin = 1;
|
||||||
|
uint32 local_data1 = 2;
|
||||||
|
uint32 local_data2 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LargeCommunitiesAttribute {
|
||||||
|
repeated LargeCommunity communities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnknownAttribute {
|
||||||
|
uint32 flags = 1;
|
||||||
|
uint32 type = 2;
|
||||||
|
bytes value = 3;
|
||||||
|
}
|
||||||
288
vendor/github.com/osrg/gobgp/api/capability.go
generated
vendored
Normal file
288
vendor/github.com/osrg/gobgp/api/capability.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
// implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package gobgpapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
proto "github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
|
|
||||||
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMultiProtocolCapability(a *bgp.CapMultiProtocol) *MultiProtocolCapability {
|
||||||
|
return &MultiProtocolCapability{
|
||||||
|
Family: Family(a.CapValue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *MultiProtocolCapability) ToNative() (*bgp.CapMultiProtocol, error) {
|
||||||
|
return bgp.NewCapMultiProtocol(bgp.RouteFamily(a.Family)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRouteRefreshCapability(a *bgp.CapRouteRefresh) *RouteRefreshCapability {
|
||||||
|
return &RouteRefreshCapability{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *RouteRefreshCapability) ToNative() (*bgp.CapRouteRefresh, error) {
|
||||||
|
return bgp.NewCapRouteRefresh(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCarryingLabelInfoCapability(a *bgp.CapCarryingLabelInfo) *CarryingLabelInfoCapability {
|
||||||
|
return &CarryingLabelInfoCapability{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CarryingLabelInfoCapability) ToNative() (*bgp.CapCarryingLabelInfo, error) {
|
||||||
|
return bgp.NewCapCarryingLabelInfo(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *ExtendedNexthopCapability {
|
||||||
|
tuples := make([]*ExtendedNexthopCapabilityTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
tuples = append(tuples, &ExtendedNexthopCapabilityTuple{
|
||||||
|
NlriFamily: Family(bgp.AfiSafiToRouteFamily(t.NLRIAFI, uint8(t.NLRISAFI))),
|
||||||
|
NexthopFamily: Family(bgp.AfiSafiToRouteFamily(t.NexthopAFI, bgp.SAFI_UNICAST)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &ExtendedNexthopCapability{
|
||||||
|
Tuples: tuples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ExtendedNexthopCapability) ToNative() (*bgp.CapExtendedNexthop, error) {
|
||||||
|
tuples := make([]*bgp.CapExtendedNexthopTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
var nhAfi uint16
|
||||||
|
switch t.NexthopFamily {
|
||||||
|
case Family_IPv4:
|
||||||
|
nhAfi = bgp.AFI_IP
|
||||||
|
case Family_IPv6:
|
||||||
|
nhAfi = bgp.AFI_IP6
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid address family for nexthop afi in extended nexthop capability: %s", t.NexthopFamily)
|
||||||
|
}
|
||||||
|
tuples = append(tuples, bgp.NewCapExtendedNexthopTuple(bgp.RouteFamily(t.NlriFamily), nhAfi))
|
||||||
|
}
|
||||||
|
return bgp.NewCapExtendedNexthop(tuples), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *GracefulRestartCapability {
|
||||||
|
tuples := make([]*GracefulRestartCapabilityTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
tuples = append(tuples, &GracefulRestartCapabilityTuple{
|
||||||
|
Family: Family(bgp.AfiSafiToRouteFamily(t.AFI, uint8(t.SAFI))),
|
||||||
|
Flags: uint32(t.Flags),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &GracefulRestartCapability{
|
||||||
|
Flags: uint32(a.Flags),
|
||||||
|
Time: uint32(a.Time),
|
||||||
|
Tuples: tuples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GracefulRestartCapability) ToNative() (*bgp.CapGracefulRestart, error) {
|
||||||
|
tuples := make([]*bgp.CapGracefulRestartTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
var forward bool
|
||||||
|
if t.Flags&0x80 > 0 {
|
||||||
|
forward = true
|
||||||
|
}
|
||||||
|
tuples = append(tuples, bgp.NewCapGracefulRestartTuple(bgp.RouteFamily(t.Family), forward))
|
||||||
|
}
|
||||||
|
var restarting bool
|
||||||
|
if a.Flags&0x08 > 0 {
|
||||||
|
restarting = true
|
||||||
|
}
|
||||||
|
var notification bool
|
||||||
|
if a.Flags&0x04 > 0 {
|
||||||
|
notification = true
|
||||||
|
}
|
||||||
|
return bgp.NewCapGracefulRestart(restarting, notification, uint16(a.Time), tuples), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *FourOctetASNumberCapability {
|
||||||
|
return &FourOctetASNumberCapability{
|
||||||
|
As: a.CapValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *FourOctetASNumberCapability) ToNative() (*bgp.CapFourOctetASNumber, error) {
|
||||||
|
return bgp.NewCapFourOctetASNumber(a.As), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAddPathCapability(a *bgp.CapAddPath) *AddPathCapability {
|
||||||
|
tuples := make([]*AddPathCapabilityTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
tuples = append(tuples, &AddPathCapabilityTuple{
|
||||||
|
Family: Family(t.RouteFamily),
|
||||||
|
Mode: AddPathMode(t.Mode),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &AddPathCapability{
|
||||||
|
Tuples: tuples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AddPathCapability) ToNative() (*bgp.CapAddPath, error) {
|
||||||
|
tuples := make([]*bgp.CapAddPathTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
tuples = append(tuples, bgp.NewCapAddPathTuple(bgp.RouteFamily(t.Family), bgp.BGPAddPathMode(t.Mode)))
|
||||||
|
}
|
||||||
|
return bgp.NewCapAddPath(tuples), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEnhancedRouteRefreshCapability(a *bgp.CapEnhancedRouteRefresh) *EnhancedRouteRefreshCapability {
|
||||||
|
return &EnhancedRouteRefreshCapability{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *EnhancedRouteRefreshCapability) ToNative() (*bgp.CapEnhancedRouteRefresh, error) {
|
||||||
|
return bgp.NewCapEnhancedRouteRefresh(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLongLivedGracefulRestartCapability(a *bgp.CapLongLivedGracefulRestart) *LongLivedGracefulRestartCapability {
|
||||||
|
tuples := make([]*LongLivedGracefulRestartCapabilityTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
tuples = append(tuples, &LongLivedGracefulRestartCapabilityTuple{
|
||||||
|
Family: Family(bgp.AfiSafiToRouteFamily(t.AFI, uint8(t.SAFI))),
|
||||||
|
Flags: uint32(t.Flags),
|
||||||
|
Time: t.RestartTime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &LongLivedGracefulRestartCapability{
|
||||||
|
Tuples: tuples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *LongLivedGracefulRestartCapability) ToNative() (*bgp.CapLongLivedGracefulRestart, error) {
|
||||||
|
tuples := make([]*bgp.CapLongLivedGracefulRestartTuple, 0, len(a.Tuples))
|
||||||
|
for _, t := range a.Tuples {
|
||||||
|
var forward bool
|
||||||
|
if t.Flags&0x80 > 0 {
|
||||||
|
forward = true
|
||||||
|
}
|
||||||
|
tuples = append(tuples, bgp.NewCapLongLivedGracefulRestartTuple(bgp.RouteFamily(t.Family), forward, t.Time))
|
||||||
|
}
|
||||||
|
return bgp.NewCapLongLivedGracefulRestart(tuples), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRouteRefreshCiscoCapability(a *bgp.CapRouteRefreshCisco) *RouteRefreshCiscoCapability {
|
||||||
|
return &RouteRefreshCiscoCapability{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *RouteRefreshCiscoCapability) ToNative() (*bgp.CapRouteRefreshCisco, error) {
|
||||||
|
return bgp.NewCapRouteRefreshCisco(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnknownCapability(a *bgp.CapUnknown) *UnknownCapability {
|
||||||
|
return &UnknownCapability{
|
||||||
|
Code: uint32(a.CapCode),
|
||||||
|
Value: a.CapValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *UnknownCapability) ToNative() (*bgp.CapUnknown, error) {
|
||||||
|
return bgp.NewCapUnknown(bgp.BGPCapabilityCode(a.Code), a.Value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalCapability(value bgp.ParameterCapabilityInterface) (*any.Any, error) {
|
||||||
|
var m proto.Message
|
||||||
|
switch n := value.(type) {
|
||||||
|
case *bgp.CapMultiProtocol:
|
||||||
|
m = NewMultiProtocolCapability(n)
|
||||||
|
case *bgp.CapRouteRefresh:
|
||||||
|
m = NewRouteRefreshCapability(n)
|
||||||
|
case *bgp.CapCarryingLabelInfo:
|
||||||
|
m = NewCarryingLabelInfoCapability(n)
|
||||||
|
case *bgp.CapExtendedNexthop:
|
||||||
|
m = NewExtendedNexthopCapability(n)
|
||||||
|
case *bgp.CapGracefulRestart:
|
||||||
|
m = NewGracefulRestartCapability(n)
|
||||||
|
case *bgp.CapFourOctetASNumber:
|
||||||
|
m = NewFourOctetASNumberCapability(n)
|
||||||
|
case *bgp.CapAddPath:
|
||||||
|
m = NewAddPathCapability(n)
|
||||||
|
case *bgp.CapEnhancedRouteRefresh:
|
||||||
|
m = NewEnhancedRouteRefreshCapability(n)
|
||||||
|
case *bgp.CapLongLivedGracefulRestart:
|
||||||
|
m = NewLongLivedGracefulRestartCapability(n)
|
||||||
|
case *bgp.CapRouteRefreshCisco:
|
||||||
|
m = NewRouteRefreshCiscoCapability(n)
|
||||||
|
case *bgp.CapUnknown:
|
||||||
|
m = NewUnknownCapability(n)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid capability type to marshal: %+v", value)
|
||||||
|
}
|
||||||
|
return ptypes.MarshalAny(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalCapabilities(values []bgp.ParameterCapabilityInterface) ([]*any.Any, error) {
|
||||||
|
caps := make([]*any.Any, 0, len(values))
|
||||||
|
for _, value := range values {
|
||||||
|
a, err := MarshalCapability(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
caps = append(caps, a)
|
||||||
|
}
|
||||||
|
return caps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalCapability(a *any.Any) (bgp.ParameterCapabilityInterface, error) {
|
||||||
|
var value ptypes.DynamicAny
|
||||||
|
if err := ptypes.UnmarshalAny(a, &value); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal capability: %s", err)
|
||||||
|
}
|
||||||
|
switch v := value.Message.(type) {
|
||||||
|
case *MultiProtocolCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *RouteRefreshCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *CarryingLabelInfoCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *ExtendedNexthopCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *GracefulRestartCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *FourOctetASNumberCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *AddPathCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *EnhancedRouteRefreshCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *LongLivedGracefulRestartCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *RouteRefreshCiscoCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
case *UnknownCapability:
|
||||||
|
return v.ToNative()
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("invalid capability type to unmarshal: %s", a.TypeUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalCapabilities(values []*any.Any) ([]bgp.ParameterCapabilityInterface, error) {
|
||||||
|
caps := make([]bgp.ParameterCapabilityInterface, 0, len(values))
|
||||||
|
for _, value := range values {
|
||||||
|
c, err := UnmarshalCapability(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
caps = append(caps, c)
|
||||||
|
}
|
||||||
|
return caps, nil
|
||||||
|
}
|
||||||
379
vendor/github.com/osrg/gobgp/api/capability.pb.go
generated
vendored
Normal file
379
vendor/github.com/osrg/gobgp/api/capability.pb.go
generated
vendored
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: capability.proto
|
||||||
|
|
||||||
|
package gobgpapi
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
type AddPathMode int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
AddPathMode_MODE_NONE AddPathMode = 0
|
||||||
|
AddPathMode_MODE_RECEIVE AddPathMode = 1
|
||||||
|
AddPathMode_MODE_SEND AddPathMode = 2
|
||||||
|
AddPathMode_MODE_BOTH AddPathMode = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
var AddPathMode_name = map[int32]string{
|
||||||
|
0: "MODE_NONE",
|
||||||
|
1: "MODE_RECEIVE",
|
||||||
|
2: "MODE_SEND",
|
||||||
|
3: "MODE_BOTH",
|
||||||
|
}
|
||||||
|
var AddPathMode_value = map[string]int32{
|
||||||
|
"MODE_NONE": 0,
|
||||||
|
"MODE_RECEIVE": 1,
|
||||||
|
"MODE_SEND": 2,
|
||||||
|
"MODE_BOTH": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x AddPathMode) String() string {
|
||||||
|
return proto.EnumName(AddPathMode_name, int32(x))
|
||||||
|
}
|
||||||
|
func (AddPathMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
|
||||||
|
|
||||||
|
type MultiProtocolCapability struct {
|
||||||
|
Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MultiProtocolCapability) Reset() { *m = MultiProtocolCapability{} }
|
||||||
|
func (m *MultiProtocolCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*MultiProtocolCapability) ProtoMessage() {}
|
||||||
|
func (*MultiProtocolCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
|
||||||
|
|
||||||
|
func (m *MultiProtocolCapability) GetFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.Family
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouteRefreshCapability struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RouteRefreshCapability) Reset() { *m = RouteRefreshCapability{} }
|
||||||
|
func (m *RouteRefreshCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*RouteRefreshCapability) ProtoMessage() {}
|
||||||
|
func (*RouteRefreshCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} }
|
||||||
|
|
||||||
|
type CarryingLabelInfoCapability struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CarryingLabelInfoCapability) Reset() { *m = CarryingLabelInfoCapability{} }
|
||||||
|
func (m *CarryingLabelInfoCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*CarryingLabelInfoCapability) ProtoMessage() {}
|
||||||
|
func (*CarryingLabelInfoCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} }
|
||||||
|
|
||||||
|
type ExtendedNexthopCapabilityTuple struct {
|
||||||
|
NlriFamily Family `protobuf:"varint,1,opt,name=nlri_family,json=nlriFamily,enum=gobgpapi.Family" json:"nlri_family,omitempty"`
|
||||||
|
// Nexthop AFI must be either
|
||||||
|
// gobgp.IPv4 or
|
||||||
|
// gobgp.IPv6.
|
||||||
|
NexthopFamily Family `protobuf:"varint,2,opt,name=nexthop_family,json=nexthopFamily,enum=gobgpapi.Family" json:"nexthop_family,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtendedNexthopCapabilityTuple) Reset() { *m = ExtendedNexthopCapabilityTuple{} }
|
||||||
|
func (m *ExtendedNexthopCapabilityTuple) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ExtendedNexthopCapabilityTuple) ProtoMessage() {}
|
||||||
|
func (*ExtendedNexthopCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} }
|
||||||
|
|
||||||
|
func (m *ExtendedNexthopCapabilityTuple) GetNlriFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.NlriFamily
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtendedNexthopCapabilityTuple) GetNexthopFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.NexthopFamily
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtendedNexthopCapability struct {
|
||||||
|
Tuples []*ExtendedNexthopCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtendedNexthopCapability) Reset() { *m = ExtendedNexthopCapability{} }
|
||||||
|
func (m *ExtendedNexthopCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ExtendedNexthopCapability) ProtoMessage() {}
|
||||||
|
func (*ExtendedNexthopCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} }
|
||||||
|
|
||||||
|
func (m *ExtendedNexthopCapability) GetTuples() []*ExtendedNexthopCapabilityTuple {
|
||||||
|
if m != nil {
|
||||||
|
return m.Tuples
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GracefulRestartCapabilityTuple struct {
|
||||||
|
Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"`
|
||||||
|
Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapabilityTuple) Reset() { *m = GracefulRestartCapabilityTuple{} }
|
||||||
|
func (m *GracefulRestartCapabilityTuple) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GracefulRestartCapabilityTuple) ProtoMessage() {}
|
||||||
|
func (*GracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} }
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapabilityTuple) GetFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.Family
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapabilityTuple) GetFlags() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Flags
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type GracefulRestartCapability struct {
|
||||||
|
Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"`
|
||||||
|
Time uint32 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
|
||||||
|
Tuples []*GracefulRestartCapabilityTuple `protobuf:"bytes,3,rep,name=tuples" json:"tuples,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapability) Reset() { *m = GracefulRestartCapability{} }
|
||||||
|
func (m *GracefulRestartCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GracefulRestartCapability) ProtoMessage() {}
|
||||||
|
func (*GracefulRestartCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} }
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapability) GetFlags() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Flags
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapability) GetTime() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Time
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GracefulRestartCapability) GetTuples() []*GracefulRestartCapabilityTuple {
|
||||||
|
if m != nil {
|
||||||
|
return m.Tuples
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FourOctetASNumberCapability struct {
|
||||||
|
As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FourOctetASNumberCapability) Reset() { *m = FourOctetASNumberCapability{} }
|
||||||
|
func (m *FourOctetASNumberCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FourOctetASNumberCapability) ProtoMessage() {}
|
||||||
|
func (*FourOctetASNumberCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} }
|
||||||
|
|
||||||
|
func (m *FourOctetASNumberCapability) GetAs() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.As
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddPathCapabilityTuple struct {
|
||||||
|
Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"`
|
||||||
|
Mode AddPathMode `protobuf:"varint,2,opt,name=mode,enum=gobgpapi.AddPathMode" json:"mode,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AddPathCapabilityTuple) Reset() { *m = AddPathCapabilityTuple{} }
|
||||||
|
func (m *AddPathCapabilityTuple) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*AddPathCapabilityTuple) ProtoMessage() {}
|
||||||
|
func (*AddPathCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{8} }
|
||||||
|
|
||||||
|
func (m *AddPathCapabilityTuple) GetFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.Family
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AddPathCapabilityTuple) GetMode() AddPathMode {
|
||||||
|
if m != nil {
|
||||||
|
return m.Mode
|
||||||
|
}
|
||||||
|
return AddPathMode_MODE_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddPathCapability struct {
|
||||||
|
Tuples []*AddPathCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AddPathCapability) Reset() { *m = AddPathCapability{} }
|
||||||
|
func (m *AddPathCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*AddPathCapability) ProtoMessage() {}
|
||||||
|
func (*AddPathCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{9} }
|
||||||
|
|
||||||
|
func (m *AddPathCapability) GetTuples() []*AddPathCapabilityTuple {
|
||||||
|
if m != nil {
|
||||||
|
return m.Tuples
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnhancedRouteRefreshCapability struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *EnhancedRouteRefreshCapability) Reset() { *m = EnhancedRouteRefreshCapability{} }
|
||||||
|
func (m *EnhancedRouteRefreshCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*EnhancedRouteRefreshCapability) ProtoMessage() {}
|
||||||
|
func (*EnhancedRouteRefreshCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{10} }
|
||||||
|
|
||||||
|
type LongLivedGracefulRestartCapabilityTuple struct {
|
||||||
|
Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"`
|
||||||
|
Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"`
|
||||||
|
Time uint32 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapabilityTuple) Reset() {
|
||||||
|
*m = LongLivedGracefulRestartCapabilityTuple{}
|
||||||
|
}
|
||||||
|
func (m *LongLivedGracefulRestartCapabilityTuple) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*LongLivedGracefulRestartCapabilityTuple) ProtoMessage() {}
|
||||||
|
func (*LongLivedGracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor2, []int{11}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapabilityTuple) GetFamily() Family {
|
||||||
|
if m != nil {
|
||||||
|
return m.Family
|
||||||
|
}
|
||||||
|
return Family_RESERVED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapabilityTuple) GetFlags() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Flags
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapabilityTuple) GetTime() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Time
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type LongLivedGracefulRestartCapability struct {
|
||||||
|
Tuples []*LongLivedGracefulRestartCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapability) Reset() { *m = LongLivedGracefulRestartCapability{} }
|
||||||
|
func (m *LongLivedGracefulRestartCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*LongLivedGracefulRestartCapability) ProtoMessage() {}
|
||||||
|
func (*LongLivedGracefulRestartCapability) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor2, []int{12}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *LongLivedGracefulRestartCapability) GetTuples() []*LongLivedGracefulRestartCapabilityTuple {
|
||||||
|
if m != nil {
|
||||||
|
return m.Tuples
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouteRefreshCiscoCapability struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *RouteRefreshCiscoCapability) Reset() { *m = RouteRefreshCiscoCapability{} }
|
||||||
|
func (m *RouteRefreshCiscoCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*RouteRefreshCiscoCapability) ProtoMessage() {}
|
||||||
|
func (*RouteRefreshCiscoCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{13} }
|
||||||
|
|
||||||
|
type UnknownCapability struct {
|
||||||
|
Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"`
|
||||||
|
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UnknownCapability) Reset() { *m = UnknownCapability{} }
|
||||||
|
func (m *UnknownCapability) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*UnknownCapability) ProtoMessage() {}
|
||||||
|
func (*UnknownCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{14} }
|
||||||
|
|
||||||
|
func (m *UnknownCapability) GetCode() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Code
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UnknownCapability) GetValue() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*MultiProtocolCapability)(nil), "gobgpapi.MultiProtocolCapability")
|
||||||
|
proto.RegisterType((*RouteRefreshCapability)(nil), "gobgpapi.RouteRefreshCapability")
|
||||||
|
proto.RegisterType((*CarryingLabelInfoCapability)(nil), "gobgpapi.CarryingLabelInfoCapability")
|
||||||
|
proto.RegisterType((*ExtendedNexthopCapabilityTuple)(nil), "gobgpapi.ExtendedNexthopCapabilityTuple")
|
||||||
|
proto.RegisterType((*ExtendedNexthopCapability)(nil), "gobgpapi.ExtendedNexthopCapability")
|
||||||
|
proto.RegisterType((*GracefulRestartCapabilityTuple)(nil), "gobgpapi.GracefulRestartCapabilityTuple")
|
||||||
|
proto.RegisterType((*GracefulRestartCapability)(nil), "gobgpapi.GracefulRestartCapability")
|
||||||
|
proto.RegisterType((*FourOctetASNumberCapability)(nil), "gobgpapi.FourOctetASNumberCapability")
|
||||||
|
proto.RegisterType((*AddPathCapabilityTuple)(nil), "gobgpapi.AddPathCapabilityTuple")
|
||||||
|
proto.RegisterType((*AddPathCapability)(nil), "gobgpapi.AddPathCapability")
|
||||||
|
proto.RegisterType((*EnhancedRouteRefreshCapability)(nil), "gobgpapi.EnhancedRouteRefreshCapability")
|
||||||
|
proto.RegisterType((*LongLivedGracefulRestartCapabilityTuple)(nil), "gobgpapi.LongLivedGracefulRestartCapabilityTuple")
|
||||||
|
proto.RegisterType((*LongLivedGracefulRestartCapability)(nil), "gobgpapi.LongLivedGracefulRestartCapability")
|
||||||
|
proto.RegisterType((*RouteRefreshCiscoCapability)(nil), "gobgpapi.RouteRefreshCiscoCapability")
|
||||||
|
proto.RegisterType((*UnknownCapability)(nil), "gobgpapi.UnknownCapability")
|
||||||
|
proto.RegisterEnum("gobgpapi.AddPathMode", AddPathMode_name, AddPathMode_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("capability.proto", fileDescriptor2) }
|
||||||
|
|
||||||
|
var fileDescriptor2 = []byte{
|
||||||
|
// 520 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6f, 0xd3, 0x4e,
|
||||||
|
0x10, 0xfd, 0x39, 0xc9, 0x2f, 0x82, 0x49, 0x13, 0xb9, 0x2b, 0x28, 0x29, 0x51, 0xa3, 0x68, 0x2f,
|
||||||
|
0x04, 0x24, 0x22, 0xb5, 0x1c, 0xe0, 0x82, 0x44, 0x49, 0x5d, 0x88, 0x94, 0x8f, 0xca, 0x2d, 0xdc,
|
||||||
|
0x50, 0xd9, 0xd8, 0x6b, 0x67, 0xc5, 0x7a, 0xd7, 0xb2, 0xd7, 0xa5, 0x39, 0x70, 0xe6, 0xc2, 0x1f,
|
||||||
|
0x8d, 0xfc, 0x11, 0xdb, 0xa4, 0x72, 0x5b, 0x21, 0x71, 0x9b, 0xf1, 0xce, 0xbc, 0x79, 0x6f, 0xde,
|
||||||
|
0xae, 0x41, 0xb7, 0x88, 0x4f, 0x96, 0x8c, 0x33, 0xb5, 0x1e, 0xf9, 0x81, 0x54, 0x12, 0x3d, 0x70,
|
||||||
|
0xe5, 0xd2, 0xf5, 0x89, 0xcf, 0x9e, 0xb6, 0x92, 0x28, 0xfd, 0x8c, 0xc7, 0xf0, 0x64, 0x16, 0x71,
|
||||||
|
0xc5, 0xce, 0xe2, 0xcc, 0x92, 0x7c, 0x9c, 0xf7, 0xa1, 0x21, 0x34, 0x1d, 0xe2, 0x31, 0xbe, 0xee,
|
||||||
|
0x6a, 0x03, 0x6d, 0xd8, 0x39, 0xd2, 0x47, 0x1b, 0x88, 0xd1, 0x69, 0xf2, 0xdd, 0xcc, 0xce, 0x71,
|
||||||
|
0x17, 0xf6, 0x4c, 0x19, 0x29, 0x6a, 0x52, 0x27, 0xa0, 0xe1, 0xaa, 0xc0, 0xc0, 0x07, 0xd0, 0x1b,
|
||||||
|
0x93, 0x20, 0x58, 0x33, 0xe1, 0x4e, 0xc9, 0x92, 0xf2, 0x89, 0x70, 0x64, 0xe9, 0xf8, 0x97, 0x06,
|
||||||
|
0x7d, 0xe3, 0x5a, 0x51, 0x61, 0x53, 0x7b, 0x4e, 0xaf, 0xd5, 0x4a, 0xfa, 0xc5, 0xe9, 0x45, 0xe4,
|
||||||
|
0x73, 0x8a, 0x0e, 0xa1, 0x25, 0x78, 0xc0, 0x2e, 0xef, 0xa0, 0x02, 0x71, 0x51, 0x1a, 0xa3, 0xd7,
|
||||||
|
0xd0, 0x11, 0x29, 0xd8, 0xa6, 0xab, 0x56, 0xd1, 0xd5, 0xce, 0xea, 0xd2, 0x14, 0x7f, 0x81, 0xfd,
|
||||||
|
0x4a, 0x36, 0xe8, 0x1d, 0x34, 0x55, 0xcc, 0x28, 0xec, 0x6a, 0x83, 0xfa, 0xb0, 0x75, 0x34, 0x2c,
|
||||||
|
0xd0, 0x6e, 0x97, 0x60, 0x66, 0x7d, 0xf8, 0x2b, 0xf4, 0x3f, 0x04, 0xc4, 0xa2, 0x4e, 0xc4, 0x4d,
|
||||||
|
0x1a, 0x2a, 0x12, 0xa8, 0x6d, 0xb1, 0xf7, 0x5e, 0x39, 0x7a, 0x04, 0xff, 0x3b, 0x9c, 0xb8, 0x61,
|
||||||
|
0x22, 0xad, 0x6d, 0xa6, 0x09, 0xfe, 0xa9, 0xc1, 0x7e, 0xe5, 0x88, 0xa2, 0x47, 0x2b, 0xf5, 0x20,
|
||||||
|
0x04, 0x0d, 0xc5, 0x3c, 0x9a, 0x01, 0x25, 0x71, 0x49, 0x6b, 0x7d, 0x5b, 0xeb, 0xed, 0x0a, 0x72,
|
||||||
|
0xad, 0x2f, 0xa1, 0x77, 0x2a, 0xa3, 0x60, 0x61, 0x29, 0xaa, 0x8e, 0xcf, 0xe7, 0x91, 0xb7, 0xa4,
|
||||||
|
0x41, 0x89, 0x4a, 0x07, 0x6a, 0x64, 0xc3, 0xa3, 0x46, 0x42, 0xec, 0xc1, 0xde, 0xb1, 0x6d, 0x9f,
|
||||||
|
0x11, 0xb5, 0xfa, 0xfb, 0x95, 0x3c, 0x87, 0x86, 0x27, 0x6d, 0x9a, 0x99, 0xfd, 0xb8, 0xa8, 0xcb,
|
||||||
|
0x90, 0x67, 0xd2, 0xa6, 0x66, 0x52, 0x82, 0x67, 0xb0, 0x7b, 0x63, 0x1c, 0x7a, 0xb3, 0x65, 0xf0,
|
||||||
|
0xe0, 0x06, 0x42, 0x95, 0xd8, 0x01, 0xf4, 0x0d, 0xb1, 0x22, 0xc2, 0xa2, 0x76, 0xc5, 0x3b, 0xf8,
|
||||||
|
0x01, 0xcf, 0xa6, 0x52, 0xb8, 0x53, 0x76, 0x45, 0xed, 0x7f, 0x7b, 0x07, 0x72, 0x3f, 0xeb, 0x85,
|
||||||
|
0x9f, 0x58, 0x02, 0xbe, 0x7b, 0x3c, 0x9a, 0x6c, 0x2d, 0xe0, 0xb0, 0x98, 0x7c, 0x4f, 0xf2, 0xf9,
|
||||||
|
0x46, 0x0e, 0xa0, 0xf7, 0xc7, 0x26, 0x58, 0x68, 0x95, 0xdf, 0xfd, 0x5b, 0xd8, 0xfd, 0x24, 0xbe,
|
||||||
|
0x09, 0xf9, 0x5d, 0x94, 0xc6, 0x23, 0x68, 0x58, 0xb1, 0x7f, 0xe9, 0xad, 0x48, 0xe2, 0x58, 0xe2,
|
||||||
|
0x15, 0xe1, 0x51, 0x6a, 0xea, 0x8e, 0x99, 0x26, 0x2f, 0xa6, 0xd0, 0x2a, 0x79, 0x8a, 0xda, 0xf0,
|
||||||
|
0x70, 0xb6, 0x38, 0x31, 0x2e, 0xe7, 0x8b, 0xb9, 0xa1, 0xff, 0x87, 0x74, 0xd8, 0x49, 0x52, 0xd3,
|
||||||
|
0x18, 0x1b, 0x93, 0xcf, 0x86, 0xae, 0xe5, 0x05, 0xe7, 0xc6, 0xfc, 0x44, 0xaf, 0xe5, 0xe9, 0xfb,
|
||||||
|
0xc5, 0xc5, 0x47, 0xbd, 0xbe, 0x6c, 0x26, 0x7f, 0xc2, 0x57, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff,
|
||||||
|
0xd6, 0xbd, 0xd3, 0xc3, 0x34, 0x05, 0x00, 0x00,
|
||||||
|
}
|
||||||
100
vendor/github.com/osrg/gobgp/api/capability.proto
generated
vendored
Normal file
100
vendor/github.com/osrg/gobgp/api/capability.proto
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation files
|
||||||
|
// (the "Software"), to deal in the Software without restriction,
|
||||||
|
// including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
// and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "gobgp.proto";
|
||||||
|
|
||||||
|
package gobgpapi;
|
||||||
|
|
||||||
|
enum AddPathMode {
|
||||||
|
MODE_NONE = 0;
|
||||||
|
MODE_RECEIVE = 1;
|
||||||
|
MODE_SEND = 2;
|
||||||
|
MODE_BOTH = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiProtocolCapability {
|
||||||
|
gobgpapi.Family family = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouteRefreshCapability {
|
||||||
|
}
|
||||||
|
|
||||||
|
message CarryingLabelInfoCapability {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtendedNexthopCapabilityTuple {
|
||||||
|
gobgpapi.Family nlri_family = 1;
|
||||||
|
// Nexthop AFI must be either
|
||||||
|
// gobgp.IPv4 or
|
||||||
|
// gobgp.IPv6.
|
||||||
|
gobgpapi.Family nexthop_family = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtendedNexthopCapability {
|
||||||
|
repeated ExtendedNexthopCapabilityTuple tuples = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GracefulRestartCapabilityTuple {
|
||||||
|
gobgpapi.Family family = 1;
|
||||||
|
uint32 flags = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GracefulRestartCapability {
|
||||||
|
uint32 flags = 1;
|
||||||
|
uint32 time = 2;
|
||||||
|
repeated GracefulRestartCapabilityTuple tuples = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FourOctetASNumberCapability {
|
||||||
|
uint32 as = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddPathCapabilityTuple {
|
||||||
|
gobgpapi.Family family = 1;
|
||||||
|
AddPathMode mode = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddPathCapability {
|
||||||
|
repeated AddPathCapabilityTuple tuples = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnhancedRouteRefreshCapability {
|
||||||
|
}
|
||||||
|
|
||||||
|
message LongLivedGracefulRestartCapabilityTuple {
|
||||||
|
gobgpapi.Family family = 1;
|
||||||
|
uint32 flags = 2;
|
||||||
|
uint32 time = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LongLivedGracefulRestartCapability {
|
||||||
|
repeated LongLivedGracefulRestartCapabilityTuple tuples = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RouteRefreshCiscoCapability {
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnknownCapability {
|
||||||
|
uint32 code = 1;
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
2634
vendor/github.com/osrg/gobgp/api/gobgp.pb.go
generated
vendored
2634
vendor/github.com/osrg/gobgp/api/gobgp.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
211
vendor/github.com/osrg/gobgp/api/gobgp.proto
generated
vendored
211
vendor/github.com/osrg/gobgp/api/gobgp.proto
generated
vendored
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/any.proto";
|
||||||
|
|
||||||
package gobgpapi;
|
package gobgpapi;
|
||||||
|
|
||||||
// Interface exported by the server.
|
// Interface exported by the server.
|
||||||
@ -31,6 +33,7 @@ service GobgpApi {
|
|||||||
rpc GetServer(GetServerRequest) returns (GetServerResponse) {}
|
rpc GetServer(GetServerRequest) returns (GetServerResponse) {}
|
||||||
rpc AddNeighbor(AddNeighborRequest) returns (AddNeighborResponse) {}
|
rpc AddNeighbor(AddNeighborRequest) returns (AddNeighborResponse) {}
|
||||||
rpc DeleteNeighbor(DeleteNeighborRequest) returns (DeleteNeighborResponse) {}
|
rpc DeleteNeighbor(DeleteNeighborRequest) returns (DeleteNeighborResponse) {}
|
||||||
|
rpc UpdateNeighbor(UpdateNeighborRequest) returns (UpdateNeighborResponse) {}
|
||||||
rpc GetNeighbor(GetNeighborRequest) returns (GetNeighborResponse) {}
|
rpc GetNeighbor(GetNeighborRequest) returns (GetNeighborResponse) {}
|
||||||
rpc ResetNeighbor(ResetNeighborRequest) returns (ResetNeighborResponse) {}
|
rpc ResetNeighbor(ResetNeighborRequest) returns (ResetNeighborResponse) {}
|
||||||
rpc SoftResetNeighbor(SoftResetNeighborRequest) returns (SoftResetNeighborResponse) {}
|
rpc SoftResetNeighbor(SoftResetNeighborRequest) returns (SoftResetNeighborResponse) {}
|
||||||
@ -73,16 +76,23 @@ service GobgpApi {
|
|||||||
rpc AddPolicy(AddPolicyRequest) returns (AddPolicyResponse) {}
|
rpc AddPolicy(AddPolicyRequest) returns (AddPolicyResponse) {}
|
||||||
rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse) {}
|
rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse) {}
|
||||||
rpc ReplacePolicy(ReplacePolicyRequest) returns (ReplacePolicyResponse) {}
|
rpc ReplacePolicy(ReplacePolicyRequest) returns (ReplacePolicyResponse) {}
|
||||||
|
rpc UpdatePolicy(UpdatePolicyRequest) returns (UpdatePolicyResponse) {}
|
||||||
rpc GetPolicyAssignment(GetPolicyAssignmentRequest) returns (GetPolicyAssignmentResponse) {}
|
rpc GetPolicyAssignment(GetPolicyAssignmentRequest) returns (GetPolicyAssignmentResponse) {}
|
||||||
rpc AddPolicyAssignment(AddPolicyAssignmentRequest) returns (AddPolicyAssignmentResponse) {}
|
rpc AddPolicyAssignment(AddPolicyAssignmentRequest) returns (AddPolicyAssignmentResponse) {}
|
||||||
rpc DeletePolicyAssignment(DeletePolicyAssignmentRequest) returns (DeletePolicyAssignmentResponse) {}
|
rpc DeletePolicyAssignment(DeletePolicyAssignmentRequest) returns (DeletePolicyAssignmentResponse) {}
|
||||||
rpc ReplacePolicyAssignment(ReplacePolicyAssignmentRequest) returns (ReplacePolicyAssignmentResponse) {}
|
rpc ReplacePolicyAssignment(ReplacePolicyAssignmentRequest) returns (ReplacePolicyAssignmentResponse) {}
|
||||||
rpc GetRibInfo(GetRibInfoRequest) returns (GetRibInfoResponse) {}
|
rpc GetRibInfo(GetRibInfoRequest) returns (GetRibInfoResponse) {}
|
||||||
|
rpc AddPeerGroup(AddPeerGroupRequest) returns (AddPeerGroupResponse) {}
|
||||||
|
rpc DeletePeerGroup(DeletePeerGroupRequest) returns (DeletePeerGroupResponse) {}
|
||||||
|
rpc UpdatePeerGroup(UpdatePeerGroupRequest) returns (UpdatePeerGroupResponse) {}
|
||||||
|
rpc AddDynamicNeighbor(AddDynamicNeighborRequest) returns (AddDynamicNeighborResponse) {}
|
||||||
|
rpc AddCollector(AddCollectorRequest) returns (AddCollectorResponse) {}
|
||||||
|
rpc Shutdown(ShutdownRequest) returns (ShutdownResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants for address families
|
// Constants for address families
|
||||||
enum Family {
|
enum Family {
|
||||||
_ = 0;
|
RESERVED = 0;
|
||||||
IPv4 = 65537;
|
IPv4 = 65537;
|
||||||
IPv6 = 131073;
|
IPv6 = 131073;
|
||||||
IPv4_MC = 65538;
|
IPv4_MC = 65538;
|
||||||
@ -157,6 +167,50 @@ message DeleteNeighborRequest {
|
|||||||
message DeleteNeighborResponse {
|
message DeleteNeighborResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message UpdateNeighborRequest {
|
||||||
|
Peer peer = 1;
|
||||||
|
// Calls SoftResetIn after updating the neighbor configuration if needed.
|
||||||
|
bool do_soft_reset_in = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateNeighborResponse {
|
||||||
|
// Indicates whether calling SoftResetIn is required due to this update. If
|
||||||
|
// "true" is set, the client should call SoftResetIn manually. If
|
||||||
|
// "do_soft_reset_in = true" is set in the request, always returned with
|
||||||
|
// "false".
|
||||||
|
bool needs_soft_reset_in = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddPeerGroupRequest {
|
||||||
|
PeerGroup peer_group = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddPeerGroupResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeletePeerGroupRequest {
|
||||||
|
PeerGroup peer_group = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeletePeerGroupResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdatePeerGroupRequest {
|
||||||
|
PeerGroup peer_group = 1;
|
||||||
|
bool do_soft_reset_in = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdatePeerGroupResponse {
|
||||||
|
bool needs_soft_reset_in = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddDynamicNeighborRequest {
|
||||||
|
DynamicNeighbor dynamic_neighbor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddDynamicNeighborResponse {
|
||||||
|
}
|
||||||
|
|
||||||
message ResetNeighborRequest {
|
message ResetNeighborRequest {
|
||||||
string address = 1;
|
string address = 1;
|
||||||
string communication = 2;
|
string communication = 2;
|
||||||
@ -201,6 +255,14 @@ message DisableNeighborRequest {
|
|||||||
message DisableNeighborResponse {
|
message DisableNeighborResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message UpdatePolicyRequest {
|
||||||
|
repeated DefinedSet sets = 1;
|
||||||
|
repeated Policy policies = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdatePolicyResponse {
|
||||||
|
}
|
||||||
|
|
||||||
message EnableMrtRequest {
|
message EnableMrtRequest {
|
||||||
int32 dump_type = 1;
|
int32 dump_type = 1;
|
||||||
string filename = 2;
|
string filename = 2;
|
||||||
@ -569,6 +631,24 @@ message Path {
|
|||||||
bool is_nexthop_invalid = 17;
|
bool is_nexthop_invalid = 17;
|
||||||
uint32 identifier = 18;
|
uint32 identifier = 18;
|
||||||
uint32 local_identifier = 19;
|
uint32 local_identifier = 19;
|
||||||
|
// One of the following defined in "api/attribute.proto":
|
||||||
|
// - IPAddressPrefix
|
||||||
|
// - LabeledIPAddressPrefix
|
||||||
|
// - EncapsulationNLRI
|
||||||
|
// - EVPNEthernetAutoDiscoveryRoute
|
||||||
|
// - EVPNMACIPAdvertisementRoute
|
||||||
|
// - EVPNInclusiveMulticastEthernetTagRoute
|
||||||
|
// - EVPNEthernetSegmentRoute
|
||||||
|
// - EVPNIPPrefixRoute
|
||||||
|
// - LabeledVPNIPAddressPrefix
|
||||||
|
// - RouteTargetMembershipNLRI
|
||||||
|
// - FlowSpecNLRI
|
||||||
|
// - VPNFlowSpecNLRI
|
||||||
|
// - OpaqueNLRI
|
||||||
|
google.protobuf.Any any_nlri = 20;
|
||||||
|
// Each attribute must be one of *Attribute defined in
|
||||||
|
// "api/attribute.proto".
|
||||||
|
repeated google.protobuf.Any any_pattrs = 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Destination {
|
message Destination {
|
||||||
@ -641,6 +721,29 @@ message Peer {
|
|||||||
AddPaths add_paths = 12;
|
AddPaths add_paths = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PeerGroup {
|
||||||
|
// Note: Regarding to the consistency with OpenConfig model, a list of
|
||||||
|
// address family should be removed from here, and should be configured with
|
||||||
|
// the list of AfiSafi instead.
|
||||||
|
repeated uint32 families = 1;
|
||||||
|
ApplyPolicy apply_policy = 2;
|
||||||
|
PeerGroupConf conf = 3;
|
||||||
|
EbgpMultihop ebgp_multihop = 4;
|
||||||
|
RouteReflector route_reflector = 5;
|
||||||
|
PeerGroupState info = 6;
|
||||||
|
Timers timers = 7;
|
||||||
|
Transport transport = 8;
|
||||||
|
RouteServer route_server = 9;
|
||||||
|
GracefulRestart graceful_restart = 10;
|
||||||
|
repeated AfiSafi afi_safis = 11;
|
||||||
|
AddPaths add_paths = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DynamicNeighbor {
|
||||||
|
string prefix = 1;
|
||||||
|
string peer_group = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message ApplyPolicy {
|
message ApplyPolicy {
|
||||||
PolicyAssignment in_policy = 1;
|
PolicyAssignment in_policy = 1;
|
||||||
PolicyAssignment export_policy = 2;
|
PolicyAssignment export_policy = 2;
|
||||||
@ -669,8 +772,10 @@ message PeerConf {
|
|||||||
RemovePrivateAs remove_private_as = 8;
|
RemovePrivateAs remove_private_as = 8;
|
||||||
bool route_flap_damping = 9;
|
bool route_flap_damping = 9;
|
||||||
uint32 send_community = 10;
|
uint32 send_community = 10;
|
||||||
repeated bytes remote_cap = 11;
|
// Each attribute must be one of *Capability defined in
|
||||||
repeated bytes local_cap = 12;
|
// "api/capability.proto".
|
||||||
|
repeated google.protobuf.Any remote_cap = 11;
|
||||||
|
repeated google.protobuf.Any local_cap = 12;
|
||||||
string id = 13;
|
string id = 13;
|
||||||
// Note: Regarding to the consistency with OpenConfig model, list of
|
// Note: Regarding to the consistency with OpenConfig model, list of
|
||||||
// PrefixLimit should be removed from here, and list of PrefixLimit in
|
// PrefixLimit should be removed from here, and list of PrefixLimit in
|
||||||
@ -683,6 +788,42 @@ message PeerConf {
|
|||||||
bool replace_peer_as = 19;
|
bool replace_peer_as = 19;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PeerGroupConf {
|
||||||
|
string auth_password = 1;
|
||||||
|
string description = 2;
|
||||||
|
uint32 local_as = 3;
|
||||||
|
uint32 peer_as = 5;
|
||||||
|
string peer_group_name = 6;
|
||||||
|
uint32 peer_type = 7;
|
||||||
|
enum RemovePrivateAs {
|
||||||
|
NONE = 0;
|
||||||
|
ALL = 1;
|
||||||
|
REPLACE = 2;
|
||||||
|
}
|
||||||
|
RemovePrivateAs remove_private_as = 8;
|
||||||
|
bool route_flap_damping = 9;
|
||||||
|
uint32 send_community = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PeerGroupState {
|
||||||
|
string auth_password = 1;
|
||||||
|
string description = 2;
|
||||||
|
uint32 local_as = 3;
|
||||||
|
uint32 peer_as = 5;
|
||||||
|
string peer_group_name = 6;
|
||||||
|
uint32 peer_type = 7;
|
||||||
|
enum RemovePrivateAs {
|
||||||
|
NONE = 0;
|
||||||
|
ALL = 1;
|
||||||
|
REPLACE = 2;
|
||||||
|
}
|
||||||
|
RemovePrivateAs remove_private_as = 8;
|
||||||
|
bool route_flap_damping = 9;
|
||||||
|
uint32 send_community = 10;
|
||||||
|
uint32 total_paths = 11;
|
||||||
|
uint32 total_prefixes = 12;
|
||||||
|
}
|
||||||
|
|
||||||
message EbgpMultihop {
|
message EbgpMultihop {
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
uint32 multihop_ttl = 2;
|
uint32 multihop_ttl = 2;
|
||||||
@ -785,6 +926,11 @@ message GracefulRestart {
|
|||||||
uint32 deferral_time = 4;
|
uint32 deferral_time = 4;
|
||||||
bool notification_enabled = 5;
|
bool notification_enabled = 5;
|
||||||
bool longlived_enabled = 6;
|
bool longlived_enabled = 6;
|
||||||
|
uint32 stale_routes_time = 7;
|
||||||
|
uint32 peer_restart_time = 8;
|
||||||
|
bool peer_restarting = 9;
|
||||||
|
bool local_restarting = 10;
|
||||||
|
string mode = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MpGracefulRestartConfig {
|
message MpGracefulRestartConfig {
|
||||||
@ -822,6 +968,7 @@ message RouteSelectionOptionsConfig {
|
|||||||
bool advertise_inactive_routes = 4;
|
bool advertise_inactive_routes = 4;
|
||||||
bool enable_aigp = 5;
|
bool enable_aigp = 5;
|
||||||
bool ignore_next_hop_igp_metric = 6;
|
bool ignore_next_hop_igp_metric = 6;
|
||||||
|
bool disable_best_path_selection = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteSelectionOptionsState {
|
message RouteSelectionOptionsState {
|
||||||
@ -831,6 +978,7 @@ message RouteSelectionOptionsState {
|
|||||||
bool advertise_inactive_routes = 4;
|
bool advertise_inactive_routes = 4;
|
||||||
bool enable_aigp = 5;
|
bool enable_aigp = 5;
|
||||||
bool ignore_next_hop_igp_metric = 6;
|
bool ignore_next_hop_igp_metric = 6;
|
||||||
|
bool disable_best_path_selection = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RouteSelectionOptions {
|
message RouteSelectionOptions {
|
||||||
@ -965,6 +1113,7 @@ enum DefinedType {
|
|||||||
COMMUNITY = 4;
|
COMMUNITY = 4;
|
||||||
EXT_COMMUNITY = 5;
|
EXT_COMMUNITY = 5;
|
||||||
LARGE_COMMUNITY = 6;
|
LARGE_COMMUNITY = 6;
|
||||||
|
NEXT_HOP = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DefinedSet {
|
message DefinedSet {
|
||||||
@ -1012,6 +1161,8 @@ message Conditions {
|
|||||||
}
|
}
|
||||||
RouteType route_type = 8;
|
RouteType route_type = 8;
|
||||||
MatchSet large_community_set = 9;
|
MatchSet large_community_set = 9;
|
||||||
|
repeated string next_hop_in_list = 10;
|
||||||
|
repeated Family afi_safi_in = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RouteAction {
|
enum RouteAction {
|
||||||
@ -1092,6 +1243,11 @@ message PolicyAssignment {
|
|||||||
RouteAction default = 5;
|
RouteAction default = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message RoutingPolicy {
|
||||||
|
repeated DefinedSet defined_set = 1;
|
||||||
|
repeated Policy policy_definition = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message Roa {
|
message Roa {
|
||||||
uint32 as = 1;
|
uint32 as = 1;
|
||||||
uint32 prefixlen = 2;
|
uint32 prefixlen = 2;
|
||||||
@ -1110,12 +1266,29 @@ message GetRoaResponse {
|
|||||||
|
|
||||||
message Vrf {
|
message Vrf {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
bytes rd = 2;
|
// Route Distinguisher must be one of
|
||||||
repeated bytes import_rt = 3;
|
// RouteDistinguisherTwoOctetAS,
|
||||||
repeated bytes export_rt = 4;
|
// RouteDistinguisherIPAddressAS,
|
||||||
|
// or RouteDistinguisherFourOctetAS.
|
||||||
|
google.protobuf.Any rd = 2;
|
||||||
|
// List of the Import Route Targets. Each must be one of
|
||||||
|
// TwoOctetAsSpecificExtended,
|
||||||
|
// IPv4AddressSpecificExtended,
|
||||||
|
// or FourOctetAsSpecificExtended.
|
||||||
|
repeated google.protobuf.Any import_rt = 3;
|
||||||
|
// List of the Export Route Targets. Each must be one of
|
||||||
|
// TwoOctetAsSpecificExtended,
|
||||||
|
// IPv4AddressSpecificExtended,
|
||||||
|
// or FourOctetAsSpecificExtended.
|
||||||
|
repeated google.protobuf.Any export_rt = 4;
|
||||||
uint32 id = 5;
|
uint32 id = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message DefaultRouteDistance {
|
||||||
|
uint32 external_route_distance = 1;
|
||||||
|
uint32 internal_route_distance = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message Global {
|
message Global {
|
||||||
uint32 as = 1;
|
uint32 as = 1;
|
||||||
string router_id = 2;
|
string router_id = 2;
|
||||||
@ -1123,6 +1296,17 @@ message Global {
|
|||||||
repeated string listen_addresses = 4;
|
repeated string listen_addresses = 4;
|
||||||
repeated uint32 families = 5;
|
repeated uint32 families = 5;
|
||||||
bool use_multiple_paths = 6;
|
bool use_multiple_paths = 6;
|
||||||
|
RouteSelectionOptionsConfig route_selection_options = 7;
|
||||||
|
DefaultRouteDistance default_route_distance = 8;
|
||||||
|
Confederation confederation = 9;
|
||||||
|
GracefulRestart graceful_restart = 10;
|
||||||
|
ApplyPolicy apply_policy = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Confederation {
|
||||||
|
bool enabled = 1;
|
||||||
|
uint32 identifier = 2;
|
||||||
|
repeated uint32 member_as_list = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TableInfo {
|
message TableInfo {
|
||||||
@ -1141,3 +1325,18 @@ message GetRibInfoRequest {
|
|||||||
message GetRibInfoResponse {
|
message GetRibInfoResponse {
|
||||||
TableInfo info = 1;
|
TableInfo info = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddCollectorRequest {
|
||||||
|
string url = 1;
|
||||||
|
string db_name = 2;
|
||||||
|
uint64 table_dump_interval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddCollectorResponse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShutdownRequest{
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShutdownResponse{
|
||||||
|
}
|
||||||
1050
vendor/github.com/osrg/gobgp/api/grpc_server.go
generated
vendored
1050
vendor/github.com/osrg/gobgp/api/grpc_server.go
generated
vendored
File diff suppressed because it is too large
Load Diff
79
vendor/github.com/osrg/gobgp/api/util.go
generated
vendored
79
vendor/github.com/osrg/gobgp/api/util.go
generated
vendored
@ -61,7 +61,7 @@ func (d *Destination) ToNativeDestination(option ...ToNativeOption) (*table.Dest
|
|||||||
if len(d.Paths) == 0 {
|
if len(d.Paths) == 0 {
|
||||||
return nil, fmt.Errorf("no path in destination")
|
return nil, fmt.Errorf("no path in destination")
|
||||||
}
|
}
|
||||||
nlri, err := getNLRI(bgp.RouteFamily(d.Paths[0].Family), d.Paths[0].Nlri)
|
nlri, err := d.Paths[0].GetNativeNlri()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -86,7 +86,30 @@ func (d *Destination) ToNativeDestination(option ...ToNativeOption) (*table.Dest
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Path) GetNativeNlri() (bgp.AddrPrefixInterface, error) {
|
func (p *Path) GetNativeNlri() (bgp.AddrPrefixInterface, error) {
|
||||||
return getNLRI(bgp.RouteFamily(p.Family), p.Nlri)
|
if len(p.Nlri) > 0 {
|
||||||
|
return getNLRI(bgp.RouteFamily(p.Family), p.Nlri)
|
||||||
|
}
|
||||||
|
return UnmarshalNLRI(bgp.RouteFamily(p.Family), p.AnyNlri)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) GetNativePathAttributes() ([]bgp.PathAttributeInterface, error) {
|
||||||
|
pattrsLen := len(p.Pattrs)
|
||||||
|
if pattrsLen > 0 {
|
||||||
|
pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen)
|
||||||
|
for _, attr := range p.Pattrs {
|
||||||
|
a, err := bgp.GetPathAttribute(attr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = a.DecodeFromBytes(attr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pattrs = append(pattrs, a)
|
||||||
|
}
|
||||||
|
return pattrs, nil
|
||||||
|
}
|
||||||
|
return UnmarshalPathAttributes(p.AnyPattrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) {
|
func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) {
|
||||||
@ -105,60 +128,54 @@ func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) {
|
|||||||
}
|
}
|
||||||
if nlri == nil {
|
if nlri == nil {
|
||||||
var err error
|
var err error
|
||||||
nlri, err = getNLRI(bgp.RouteFamily(p.Family), p.Nlri)
|
nlri, err = p.GetNativeNlri()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
|
pattr, err := p.GetNativePathAttributes()
|
||||||
for _, attr := range p.Pattrs {
|
if err != nil {
|
||||||
p, err := bgp.GetPathAttribute(attr)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = p.DecodeFromBytes(attr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pattr = append(pattr, p)
|
|
||||||
}
|
}
|
||||||
t := time.Unix(p.Age, 0)
|
t := time.Unix(p.Age, 0)
|
||||||
nlri.SetPathIdentifier(p.Identifier)
|
nlri.SetPathIdentifier(p.Identifier)
|
||||||
nlri.SetPathLocalIdentifier(p.LocalIdentifier)
|
nlri.SetPathLocalIdentifier(p.LocalIdentifier)
|
||||||
path := table.NewPath(info, nlri, p.IsWithdraw, pattr, t, false)
|
path := table.NewPath(info, nlri, p.IsWithdraw, pattr, t, false)
|
||||||
|
|
||||||
|
// p.ValidationDetail.* are already validated
|
||||||
|
matched, _ := NewROAListFromApiStructList(p.ValidationDetail.Matched)
|
||||||
|
unmatchedAs, _ := NewROAListFromApiStructList(p.ValidationDetail.UnmatchedAs)
|
||||||
|
unmatchedLength, _ := NewROAListFromApiStructList(p.ValidationDetail.UnmatchedLength)
|
||||||
|
|
||||||
path.SetValidation(&table.Validation{
|
path.SetValidation(&table.Validation{
|
||||||
Status: config.IntToRpkiValidationResultTypeMap[int(p.Validation)],
|
Status: config.IntToRpkiValidationResultTypeMap[int(p.Validation)],
|
||||||
Reason: table.IntToRpkiValidationReasonTypeMap[int(p.ValidationDetail.Reason)],
|
Reason: table.IntToRpkiValidationReasonTypeMap[int(p.ValidationDetail.Reason)],
|
||||||
Matched: NewROAListFromApiStructList(p.ValidationDetail.Matched),
|
Matched: matched,
|
||||||
UnmatchedAs: NewROAListFromApiStructList(p.ValidationDetail.UnmatchedAs),
|
UnmatchedAs: unmatchedAs,
|
||||||
UnmatchedLength: NewROAListFromApiStructList(p.ValidationDetail.UnmatchedLength),
|
UnmatchedLength: unmatchedLength,
|
||||||
})
|
})
|
||||||
path.MarkStale(p.Stale)
|
path.MarkStale(p.Stale)
|
||||||
path.SetUUID(p.Uuid)
|
|
||||||
if p.Filtered {
|
|
||||||
path.Filter("", table.POLICY_DIRECTION_IN)
|
|
||||||
}
|
|
||||||
path.IsNexthopInvalid = p.IsNexthopInvalid
|
path.IsNexthopInvalid = p.IsNexthopInvalid
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewROAListFromApiStructList(l []*Roa) []*table.ROA {
|
func NewROAListFromApiStructList(l []*Roa) ([]*table.ROA, error) {
|
||||||
roas := make([]*table.ROA, 0, len(l))
|
roas := make([]*table.ROA, 0, len(l))
|
||||||
for _, r := range l {
|
for _, r := range l {
|
||||||
ip := net.ParseIP(r.Prefix)
|
ip := net.ParseIP(r.Prefix)
|
||||||
rf := func(prefix string) bgp.RouteFamily {
|
family := bgp.RF_IPv4_UC
|
||||||
a, _, _ := net.ParseCIDR(prefix)
|
if ip == nil {
|
||||||
if a.To4() != nil {
|
return nil, fmt.Errorf("invalid prefix %s", r.Prefix)
|
||||||
return bgp.RF_IPv4_UC
|
} else {
|
||||||
} else {
|
if ip.To4() == nil {
|
||||||
return bgp.RF_IPv6_UC
|
family = bgp.RF_IPv6_UC
|
||||||
}
|
}
|
||||||
}(r.Prefix)
|
}
|
||||||
afi, _ := bgp.RouteFamilyToAfiSafi(rf)
|
afi, _ := bgp.RouteFamilyToAfiSafi(family)
|
||||||
roa := table.NewROA(int(afi), []byte(ip), uint8(r.Prefixlen), uint8(r.Maxlen), r.As, net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort))
|
roa := table.NewROA(int(afi), []byte(ip), uint8(r.Prefixlen), uint8(r.Maxlen), r.As, net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort))
|
||||||
roas = append(roas, roa)
|
roas = append(roas, roa)
|
||||||
}
|
}
|
||||||
return roas
|
return roas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractFamilyFromConfigAfiSafi(c *config.AfiSafi) uint32 {
|
func extractFamilyFromConfigAfiSafi(c *config.AfiSafi) uint32 {
|
||||||
|
|||||||
102
vendor/github.com/osrg/gobgp/client/client.go
generated
vendored
102
vendor/github.com/osrg/gobgp/client/client.go
generated
vendored
@ -198,8 +198,11 @@ func (cli *Client) DeleteNeighbor(c *config.Neighbor) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (cli *Client) UpdateNeighbor(c *config.Neighbor) (bool, error) {
|
func (cli *Client) UpdateNeighbor(c *config.Neighbor, doSoftResetIn bool) (bool, error) {
|
||||||
//}
|
peer := api.NewPeerFromConfigStruct(c)
|
||||||
|
response, err := cli.cli.UpdateNeighbor(context.Background(), &api.UpdateNeighborRequest{Peer: peer, DoSoftResetIn: doSoftResetIn})
|
||||||
|
return response.NeedsSoftResetIn, err
|
||||||
|
}
|
||||||
|
|
||||||
func (cli *Client) ShutdownNeighbor(addr, communication string) error {
|
func (cli *Client) ShutdownNeighbor(addr, communication string) error {
|
||||||
_, err := cli.cli.ShutdownNeighbor(context.Background(), &api.ShutdownNeighborRequest{Address: addr, Communication: communication})
|
_, err := cli.cli.ShutdownNeighbor(context.Background(), &api.ShutdownNeighborRequest{Address: addr, Communication: communication})
|
||||||
@ -354,7 +357,7 @@ type AddPathByStreamClient struct {
|
|||||||
func (c *AddPathByStreamClient) Send(paths ...*table.Path) error {
|
func (c *AddPathByStreamClient) Send(paths ...*table.Path) error {
|
||||||
ps := make([]*api.Path, 0, len(paths))
|
ps := make([]*api.Path, 0, len(paths))
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
ps = append(ps, api.ToPathApi(p))
|
ps = append(ps, api.ToPathApiInBin(p, nil))
|
||||||
}
|
}
|
||||||
return c.stream.Send(&api.InjectMrtRequest{
|
return c.stream.Send(&api.InjectMrtRequest{
|
||||||
Resource: api.Resource_GLOBAL,
|
Resource: api.Resource_GLOBAL,
|
||||||
@ -385,7 +388,7 @@ func (cli *Client) addPath(vrfID string, pathList []*table.Path) ([]byte, error)
|
|||||||
r, err := cli.cli.AddPath(context.Background(), &api.AddPathRequest{
|
r, err := cli.cli.AddPath(context.Background(), &api.AddPathRequest{
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
VrfId: vrfID,
|
VrfId: vrfID,
|
||||||
Path: api.ToPathApi(path),
|
Path: api.ToPathApi(path, nil),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -416,21 +419,10 @@ func (cli *Client) deletePath(uuid []byte, f bgp.RouteFamily, vrfID string, path
|
|||||||
switch {
|
switch {
|
||||||
case len(pathList) != 0:
|
case len(pathList) != 0:
|
||||||
for _, path := range pathList {
|
for _, path := range pathList {
|
||||||
nlri := path.GetNlri()
|
|
||||||
n, err := nlri.Serialize()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p := &api.Path{
|
|
||||||
Nlri: n,
|
|
||||||
Family: uint32(path.GetRouteFamily()),
|
|
||||||
Identifier: nlri.PathIdentifier(),
|
|
||||||
LocalIdentifier: nlri.PathLocalIdentifier(),
|
|
||||||
}
|
|
||||||
reqs = append(reqs, &api.DeletePathRequest{
|
reqs = append(reqs, &api.DeletePathRequest{
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
VrfId: vrfID,
|
VrfId: vrfID,
|
||||||
Path: p,
|
Path: api.ToPathApi(path, nil),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -469,83 +461,25 @@ func (cli *Client) DeletePathByFamily(family bgp.RouteFamily) error {
|
|||||||
return cli.deletePath(nil, family, "", nil)
|
return cli.deletePath(nil, family, "", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) GetVRF() ([]*table.Vrf, error) {
|
func (cli *Client) GetVRF() ([]*api.Vrf, error) {
|
||||||
ret, err := cli.cli.GetVrf(context.Background(), &api.GetVrfRequest{})
|
ret, err := cli.cli.GetVrf(context.Background(), &api.GetVrfRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var vrfs []*table.Vrf
|
return ret.Vrfs, nil
|
||||||
|
|
||||||
f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) {
|
|
||||||
ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs))
|
|
||||||
for _, rt := range bufs {
|
|
||||||
r, err := bgp.ParseExtended(rt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret = append(ret, r)
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, vrf := range ret.Vrfs {
|
|
||||||
importRT, err := f(vrf.ImportRt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
exportRT, err := f(vrf.ExportRt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vrfs = append(vrfs, &table.Vrf{
|
|
||||||
Name: vrf.Name,
|
|
||||||
Id: vrf.Id,
|
|
||||||
Rd: bgp.GetRouteDistinguisher(vrf.Rd),
|
|
||||||
ImportRt: importRT,
|
|
||||||
ExportRt: exportRT,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return vrfs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) AddVRF(name string, id int, rd bgp.RouteDistinguisherInterface, im, ex []bgp.ExtendedCommunityInterface) error {
|
func (cli *Client) AddVRF(name string, id int, rd bgp.RouteDistinguisherInterface, im, ex []bgp.ExtendedCommunityInterface) error {
|
||||||
buf, err := rd.Serialize()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(comms []bgp.ExtendedCommunityInterface) ([][]byte, error) {
|
|
||||||
var bufs [][]byte
|
|
||||||
for _, c := range comms {
|
|
||||||
buf, err := c.Serialize()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bufs = append(bufs, buf)
|
|
||||||
}
|
|
||||||
return bufs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
importRT, err := f(im)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
exportRT, err := f(ex)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
arg := &api.AddVrfRequest{
|
arg := &api.AddVrfRequest{
|
||||||
Vrf: &api.Vrf{
|
Vrf: &api.Vrf{
|
||||||
Name: name,
|
Name: name,
|
||||||
Rd: buf,
|
Rd: api.MarshalRD(rd),
|
||||||
Id: uint32(id),
|
Id: uint32(id),
|
||||||
ImportRt: importRT,
|
ImportRt: api.MarshalRTs(im),
|
||||||
ExportRt: exportRT,
|
ExportRt: api.MarshalRTs(ex),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = cli.cli.AddVrf(context.Background(), arg)
|
_, err := cli.cli.AddVrf(context.Background(), arg)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,8 +652,6 @@ func (cli *Client) ReplacePolicy(t *table.Policy, refer, preserve bool) error {
|
|||||||
func (cli *Client) getPolicyAssignment(name string, dir table.PolicyDirection) (*table.PolicyAssignment, error) {
|
func (cli *Client) getPolicyAssignment(name string, dir table.PolicyDirection) (*table.PolicyAssignment, error) {
|
||||||
var typ api.PolicyType
|
var typ api.PolicyType
|
||||||
switch dir {
|
switch dir {
|
||||||
case table.POLICY_DIRECTION_IN:
|
|
||||||
typ = api.PolicyType_IN
|
|
||||||
case table.POLICY_DIRECTION_IMPORT:
|
case table.POLICY_DIRECTION_IMPORT:
|
||||||
typ = api.PolicyType_IMPORT
|
typ = api.PolicyType_IMPORT
|
||||||
case table.POLICY_DIRECTION_EXPORT:
|
case table.POLICY_DIRECTION_EXPORT:
|
||||||
@ -770,10 +702,6 @@ func (cli *Client) GetExportPolicy() (*table.PolicyAssignment, error) {
|
|||||||
return cli.getPolicyAssignment("", table.POLICY_DIRECTION_EXPORT)
|
return cli.getPolicyAssignment("", table.POLICY_DIRECTION_EXPORT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) GetRouteServerInPolicy(name string) (*table.PolicyAssignment, error) {
|
|
||||||
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_IN)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cli *Client) GetRouteServerImportPolicy(name string) (*table.PolicyAssignment, error) {
|
func (cli *Client) GetRouteServerImportPolicy(name string) (*table.PolicyAssignment, error) {
|
||||||
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_IMPORT)
|
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_IMPORT)
|
||||||
}
|
}
|
||||||
@ -867,7 +795,7 @@ func (cli *Client) GetROA(family bgp.RouteFamily) ([]*table.ROA, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return api.NewROAListFromApiStructList(rsp.Roas), nil
|
return api.NewROAListFromApiStructList(rsp.Roas)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) AddRPKIServer(address string, port, lifetime int) error {
|
func (cli *Client) AddRPKIServer(address string, port, lifetime int) error {
|
||||||
|
|||||||
128
vendor/github.com/osrg/gobgp/config/bgp_configs.go
generated
vendored
128
vendor/github.com/osrg/gobgp/config/bgp_configs.go
generated
vendored
@ -1114,7 +1114,7 @@ type ZebraState struct {
|
|||||||
// Configure url for zebra.
|
// Configure url for zebra.
|
||||||
Url string `mapstructure:"url" json:"url,omitempty"`
|
Url string `mapstructure:"url" json:"url,omitempty"`
|
||||||
// original -> gobgp:redistribute-route-type
|
// original -> gobgp:redistribute-route-type
|
||||||
RedistributeRouteTypeList []InstallProtocolType `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
|
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
|
||||||
// original -> gobgp:version
|
// original -> gobgp:version
|
||||||
// Configure version of zebra protocol. Default is 2. Supported up to 3.
|
// Configure version of zebra protocol. Default is 2. Supported up to 3.
|
||||||
Version uint8 `mapstructure:"version" json:"version,omitempty"`
|
Version uint8 `mapstructure:"version" json:"version,omitempty"`
|
||||||
@ -1135,7 +1135,7 @@ type ZebraConfig struct {
|
|||||||
// Configure url for zebra.
|
// Configure url for zebra.
|
||||||
Url string `mapstructure:"url" json:"url,omitempty"`
|
Url string `mapstructure:"url" json:"url,omitempty"`
|
||||||
// original -> gobgp:redistribute-route-type
|
// original -> gobgp:redistribute-route-type
|
||||||
RedistributeRouteTypeList []InstallProtocolType `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
|
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
|
||||||
// original -> gobgp:version
|
// original -> gobgp:version
|
||||||
// Configure version of zebra protocol. Default is 2. Supported up to 3.
|
// Configure version of zebra protocol. Default is 2. Supported up to 3.
|
||||||
Version uint8 `mapstructure:"version" json:"version,omitempty"`
|
Version uint8 `mapstructure:"version" json:"version,omitempty"`
|
||||||
@ -1249,6 +1249,112 @@ func (lhs *Mrt) Equal(rhs *Mrt) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct for container gobgp:state.
|
||||||
|
// Configured states of VRF.
|
||||||
|
type VrfState struct {
|
||||||
|
// original -> gobgp:name
|
||||||
|
// Unique name among all VRF instances.
|
||||||
|
Name string `mapstructure:"name" json:"name,omitempty"`
|
||||||
|
// original -> gobgp:id
|
||||||
|
// Unique identifier among all VRF instances.
|
||||||
|
Id uint32 `mapstructure:"id" json:"id,omitempty"`
|
||||||
|
// original -> gobgp:rd
|
||||||
|
// Route Distinguisher for this VRF.
|
||||||
|
Rd string `mapstructure:"rd" json:"rd,omitempty"`
|
||||||
|
// original -> gobgp:import-rt
|
||||||
|
// List of import Route Targets for this VRF.
|
||||||
|
ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"`
|
||||||
|
// original -> gobgp:export-rt
|
||||||
|
// List of export Route Targets for this VRF.
|
||||||
|
ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct for container gobgp:config.
|
||||||
|
// Configuration parameters for VRF.
|
||||||
|
type VrfConfig struct {
|
||||||
|
// original -> gobgp:name
|
||||||
|
// Unique name among all VRF instances.
|
||||||
|
Name string `mapstructure:"name" json:"name,omitempty"`
|
||||||
|
// original -> gobgp:id
|
||||||
|
// Unique identifier among all VRF instances.
|
||||||
|
Id uint32 `mapstructure:"id" json:"id,omitempty"`
|
||||||
|
// original -> gobgp:rd
|
||||||
|
// Route Distinguisher for this VRF.
|
||||||
|
Rd string `mapstructure:"rd" json:"rd,omitempty"`
|
||||||
|
// original -> gobgp:import-rt
|
||||||
|
// List of import Route Targets for this VRF.
|
||||||
|
ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"`
|
||||||
|
// original -> gobgp:export-rt
|
||||||
|
// List of export Route Targets for this VRF.
|
||||||
|
ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"`
|
||||||
|
// original -> gobgp:both-rt
|
||||||
|
// List of both import and export Route Targets for this VRF. Each
|
||||||
|
// configuration for import and export Route Targets will be preferred.
|
||||||
|
BothRtList []string `mapstructure:"both-rt-list" json:"both-rt-list,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lhs *VrfConfig) Equal(rhs *VrfConfig) bool {
|
||||||
|
if lhs == nil || rhs == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.Name != rhs.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.Id != rhs.Id {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.Rd != rhs.Rd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(lhs.ImportRtList) != len(rhs.ImportRtList) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for idx, l := range lhs.ImportRtList {
|
||||||
|
if l != rhs.ImportRtList[idx] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lhs.ExportRtList) != len(rhs.ExportRtList) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for idx, l := range lhs.ExportRtList {
|
||||||
|
if l != rhs.ExportRtList[idx] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(lhs.BothRtList) != len(rhs.BothRtList) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for idx, l := range lhs.BothRtList {
|
||||||
|
if l != rhs.BothRtList[idx] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct for container gobgp:vrf.
|
||||||
|
// VRF instance configurations on the local system.
|
||||||
|
type Vrf struct {
|
||||||
|
// original -> gobgp:name
|
||||||
|
// original -> gobgp:vrf-config
|
||||||
|
// Configuration parameters for VRF.
|
||||||
|
Config VrfConfig `mapstructure:"config" json:"config,omitempty"`
|
||||||
|
// original -> gobgp:vrf-state
|
||||||
|
// Configured states of VRF.
|
||||||
|
State VrfState `mapstructure:"state" json:"state,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lhs *Vrf) Equal(rhs *Vrf) bool {
|
||||||
|
if lhs == nil || rhs == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !lhs.Config.Equal(&(rhs.Config)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// struct for container gobgp:state.
|
// struct for container gobgp:state.
|
||||||
// Configuration parameters relating to BMP server.
|
// Configuration parameters relating to BMP server.
|
||||||
type BmpServerState struct {
|
type BmpServerState struct {
|
||||||
@ -4785,6 +4891,8 @@ type Bgp struct {
|
|||||||
RpkiServers []RpkiServer `mapstructure:"rpki-servers" json:"rpki-servers,omitempty"`
|
RpkiServers []RpkiServer `mapstructure:"rpki-servers" json:"rpki-servers,omitempty"`
|
||||||
// original -> gobgp:bmp-servers
|
// original -> gobgp:bmp-servers
|
||||||
BmpServers []BmpServer `mapstructure:"bmp-servers" json:"bmp-servers,omitempty"`
|
BmpServers []BmpServer `mapstructure:"bmp-servers" json:"bmp-servers,omitempty"`
|
||||||
|
// original -> gobgp:vrfs
|
||||||
|
Vrfs []Vrf `mapstructure:"vrfs" json:"vrfs,omitempty"`
|
||||||
// original -> gobgp:mrt-dump
|
// original -> gobgp:mrt-dump
|
||||||
MrtDump []Mrt `mapstructure:"mrt-dump" json:"mrt-dump,omitempty"`
|
MrtDump []Mrt `mapstructure:"mrt-dump" json:"mrt-dump,omitempty"`
|
||||||
// original -> gobgp:zebra
|
// original -> gobgp:zebra
|
||||||
@ -4866,6 +4974,22 @@ func (lhs *Bgp) Equal(rhs *Bgp) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(lhs.Vrfs) != len(rhs.Vrfs) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lmap := make(map[string]*Vrf)
|
||||||
|
for i, l := range lhs.Vrfs {
|
||||||
|
lmap[mapkey(i, string(l.Config.Name))] = &lhs.Vrfs[i]
|
||||||
|
}
|
||||||
|
for i, r := range rhs.Vrfs {
|
||||||
|
if l, y := lmap[mapkey(i, string(r.Config.Name))]; !y {
|
||||||
|
return false
|
||||||
|
} else if !r.Equal(l) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(lhs.MrtDump) != len(rhs.MrtDump) {
|
if len(lhs.MrtDump) != len(rhs.MrtDump) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
105
vendor/github.com/osrg/gobgp/config/default.go
generated
vendored
105
vendor/github.com/osrg/gobgp/config/default.go
generated
vendored
@ -1,14 +1,18 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
"github.com/osrg/gobgp/packet/bmp"
|
"github.com/osrg/gobgp/packet/bmp"
|
||||||
"github.com/osrg/gobgp/packet/rtr"
|
"github.com/osrg/gobgp/packet/rtr"
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,7 +30,7 @@ var configuredFields map[string]interface{}
|
|||||||
|
|
||||||
func RegisterConfiguredFields(addr string, n interface{}) {
|
func RegisterConfiguredFields(addr string, n interface{}) {
|
||||||
if configuredFields == nil {
|
if configuredFields == nil {
|
||||||
configuredFields = make(map[string]interface{}, 0)
|
configuredFields = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
configuredFields[addr] = n
|
configuredFields[addr] = n
|
||||||
}
|
}
|
||||||
@ -183,11 +187,11 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Glo
|
|||||||
if len(afs) > i {
|
if len(afs) > i {
|
||||||
vv.Set("afi-safi", afs[i])
|
vv.Set("afi-safi", afs[i])
|
||||||
}
|
}
|
||||||
if rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName)); err != nil {
|
rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName))
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
|
||||||
n.AfiSafis[i].State.Family = rf
|
|
||||||
}
|
}
|
||||||
|
n.AfiSafis[i].State.Family = rf
|
||||||
n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName
|
n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName
|
||||||
if !vv.IsSet("afi-safi.config.enabled") {
|
if !vv.IsSet("afi-safi.config.enabled") {
|
||||||
n.AfiSafis[i].Config.Enabled = true
|
n.AfiSafis[i].Config.Enabled = true
|
||||||
@ -238,9 +242,18 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Glo
|
|||||||
|
|
||||||
if n.RouteReflector.Config.RouteReflectorClient {
|
if n.RouteReflector.Config.RouteReflectorClient {
|
||||||
if n.RouteReflector.Config.RouteReflectorClusterId == "" {
|
if n.RouteReflector.Config.RouteReflectorClusterId == "" {
|
||||||
n.RouteReflector.Config.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId)
|
n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId)
|
||||||
} else if id := net.ParseIP(string(n.RouteReflector.Config.RouteReflectorClusterId)).To4(); id == nil {
|
} else {
|
||||||
return fmt.Errorf("route-reflector-cluster-id should be specified in IPv4 address format")
|
id := string(n.RouteReflector.Config.RouteReflectorClusterId)
|
||||||
|
if ip := net.ParseIP(id).To4(); ip != nil {
|
||||||
|
n.RouteReflector.State.RouteReflectorClusterId = n.RouteReflector.Config.RouteReflectorClusterId
|
||||||
|
} else if num, err := strconv.ParseUint(id, 10, 32); err == nil {
|
||||||
|
ip = make(net.IP, 4)
|
||||||
|
binary.BigEndian.PutUint32(ip, uint32(num))
|
||||||
|
n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(ip.String())
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("route-reflector-cluster-id should be specified as IPv4 address or 32-bit unsigned integer")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +263,7 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Glo
|
|||||||
func SetDefaultGlobalConfigValues(g *Global) error {
|
func SetDefaultGlobalConfigValues(g *Global) error {
|
||||||
if len(g.AfiSafis) == 0 {
|
if len(g.AfiSafis) == 0 {
|
||||||
g.AfiSafis = []AfiSafi{}
|
g.AfiSafis = []AfiSafi{}
|
||||||
for k, _ := range AfiSafiTypeToIntMap {
|
for k := range AfiSafiTypeToIntMap {
|
||||||
g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true))
|
g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,6 +278,43 @@ func SetDefaultGlobalConfigValues(g *Global) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setDefaultVrfConfigValues(v *Vrf) error {
|
||||||
|
if v == nil {
|
||||||
|
return fmt.Errorf("cannot set default values for nil vrf config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Config.Name == "" {
|
||||||
|
return fmt.Errorf("specify vrf name")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := bgp.ParseRouteDistinguisher(v.Config.Rd)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid rd for vrf %s: %s", v.Config.Name, v.Config.Rd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.Config.ImportRtList) == 0 {
|
||||||
|
v.Config.ImportRtList = v.Config.BothRtList
|
||||||
|
}
|
||||||
|
for _, rtString := range v.Config.ImportRtList {
|
||||||
|
_, err := bgp.ParseRouteTarget(rtString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid import rt for vrf %s: %s", v.Config.Name, rtString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.Config.ExportRtList) == 0 {
|
||||||
|
v.Config.ExportRtList = v.Config.BothRtList
|
||||||
|
}
|
||||||
|
for _, rtString := range v.Config.ExportRtList {
|
||||||
|
_, err := bgp.ParseRouteTarget(rtString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid export rt for vrf %s: %s", v.Config.Name, rtString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func SetDefaultConfigValues(b *BgpConfigSet) error {
|
func SetDefaultConfigValues(b *BgpConfigSet) error {
|
||||||
return setDefaultConfigValuesWithViper(nil, b)
|
return setDefaultConfigValuesWithViper(nil, b)
|
||||||
}
|
}
|
||||||
@ -274,7 +324,7 @@ func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for i, _ := range p.Statements {
|
for i := range p.Statements {
|
||||||
vv := viper.New()
|
vv := viper.New()
|
||||||
if len(stmts) > i {
|
if len(stmts) > i {
|
||||||
vv.Set("statement", stmts[i])
|
vv.Set("statement", stmts[i])
|
||||||
@ -309,6 +359,41 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
|
|||||||
b.BmpServers[idx] = server
|
b.BmpServers[idx] = server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vrfNames := make(map[string]struct{})
|
||||||
|
vrfIDs := make(map[uint32]struct{})
|
||||||
|
for idx, vrf := range b.Vrfs {
|
||||||
|
if err := setDefaultVrfConfigValues(&vrf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := vrfNames[vrf.Config.Name]; ok {
|
||||||
|
return fmt.Errorf("duplicated vrf name: %s", vrf.Config.Name)
|
||||||
|
}
|
||||||
|
vrfNames[vrf.Config.Name] = struct{}{}
|
||||||
|
|
||||||
|
if vrf.Config.Id != 0 {
|
||||||
|
if _, ok := vrfIDs[vrf.Config.Id]; ok {
|
||||||
|
return fmt.Errorf("duplicated vrf id: %d", vrf.Config.Id)
|
||||||
|
}
|
||||||
|
vrfIDs[vrf.Config.Id] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Vrfs[idx] = vrf
|
||||||
|
}
|
||||||
|
// Auto assign VRF identifier
|
||||||
|
for idx, vrf := range b.Vrfs {
|
||||||
|
if vrf.Config.Id == 0 {
|
||||||
|
for id := uint32(1); id < math.MaxUint32; id++ {
|
||||||
|
if _, ok := vrfIDs[id]; !ok {
|
||||||
|
vrf.Config.Id = id
|
||||||
|
vrfIDs[id] = struct{}{}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Vrfs[idx] = vrf
|
||||||
|
}
|
||||||
|
|
||||||
if b.Zebra.Config.Url == "" {
|
if b.Zebra.Config.Url == "" {
|
||||||
b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
|
b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
|
||||||
}
|
}
|
||||||
|
|||||||
22
vendor/github.com/osrg/gobgp/config/default_linux.go
generated
vendored
22
vendor/github.com/osrg/gobgp/config/default_linux.go
generated
vendored
@ -18,8 +18,9 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
||||||
@ -40,7 +41,7 @@ func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
|||||||
}
|
}
|
||||||
if neigh.State&netlink.NUD_FAILED == 0 && neigh.IP.IsLinkLocalUnicast() && !local {
|
if neigh.State&netlink.NUD_FAILED == 0 && neigh.IP.IsLinkLocalUnicast() && !local {
|
||||||
addr = neigh.IP
|
addr = neigh.IP
|
||||||
cnt += 1
|
cnt++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,3 +53,20 @@ func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
|||||||
|
|
||||||
return fmt.Sprintf("%s%%%s", addr, ifname), nil
|
return fmt.Sprintf("%s%%%s", addr, ifname), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) {
|
||||||
|
ifi, err := net.InterfaceByIndex(ifindex)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
addrs, err := ifi.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
for _, a := range addrs {
|
||||||
|
if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|||||||
19
vendor/github.com/osrg/gobgp/config/serve.go
generated
vendored
19
vendor/github.com/osrg/gobgp/config/serve.go
generated
vendored
@ -1,11 +1,12 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BgpConfigSet struct {
|
type BgpConfigSet struct {
|
||||||
@ -14,6 +15,7 @@ type BgpConfigSet struct {
|
|||||||
PeerGroups []PeerGroup `mapstructure:"peer-groups"`
|
PeerGroups []PeerGroup `mapstructure:"peer-groups"`
|
||||||
RpkiServers []RpkiServer `mapstructure:"rpki-servers"`
|
RpkiServers []RpkiServer `mapstructure:"rpki-servers"`
|
||||||
BmpServers []BmpServer `mapstructure:"bmp-servers"`
|
BmpServers []BmpServer `mapstructure:"bmp-servers"`
|
||||||
|
Vrfs []Vrf `mapstructure:"vrfs"`
|
||||||
MrtDump []Mrt `mapstructure:"mrt-dump"`
|
MrtDump []Mrt `mapstructure:"mrt-dump"`
|
||||||
Zebra Zebra `mapstructure:"zebra"`
|
Zebra Zebra `mapstructure:"zebra"`
|
||||||
Collector Collector `mapstructure:"collector"`
|
Collector Collector `mapstructure:"collector"`
|
||||||
@ -66,12 +68,10 @@ func ReadConfigfileServe(path, format string, configCh chan *BgpConfigSet) {
|
|||||||
}).Warningf("Can't read config file %s", path)
|
}).Warningf("Can't read config file %s", path)
|
||||||
}
|
}
|
||||||
NEXT:
|
NEXT:
|
||||||
select {
|
<-sigCh
|
||||||
case <-sigCh:
|
log.WithFields(log.Fields{
|
||||||
log.WithFields(log.Fields{
|
"Topic": "Config",
|
||||||
"Topic": "Config",
|
}).Info("Reload the config file")
|
||||||
}).Info("Reload the config file")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +145,8 @@ func CheckPolicyDifference(currentPolicy *RoutingPolicy, newPolicy *RoutingPolic
|
|||||||
"Topic": "Config",
|
"Topic": "Config",
|
||||||
}).Debugf("New policy:%s", newPolicy)
|
}).Debugf("New policy:%s", newPolicy)
|
||||||
|
|
||||||
var result bool = false
|
var result bool
|
||||||
if currentPolicy == nil && newPolicy == nil {
|
if currentPolicy == nil && newPolicy == nil {
|
||||||
|
|
||||||
result = false
|
result = false
|
||||||
} else {
|
} else {
|
||||||
if currentPolicy != nil && newPolicy != nil {
|
if currentPolicy != nil && newPolicy != nil {
|
||||||
|
|||||||
33
vendor/github.com/osrg/gobgp/config/util.go
generated
vendored
33
vendor/github.com/osrg/gobgp/config/util.go
generated
vendored
@ -81,23 +81,6 @@ func getIPv6LinkLocalAddress(ifname string) (string, error) {
|
|||||||
return "", fmt.Errorf("no ipv6 link local address for %s", ifname)
|
return "", fmt.Errorf("no ipv6 link local address for %s", ifname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) {
|
|
||||||
ifi, err := net.InterfaceByIndex(ifindex)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
addrs, err := ifi.Addrs()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
for _, a := range addrs {
|
|
||||||
if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) {
|
func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) {
|
||||||
if n == "" {
|
if n == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -216,7 +199,7 @@ func existPeerGroup(n string, b []PeerGroup) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckAfiSafisChange(x, y []AfiSafi) bool {
|
func isAfiSafiChanged(x, y []AfiSafi) bool {
|
||||||
if len(x) != len(y) {
|
if len(x) != len(y) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -232,6 +215,17 @@ func CheckAfiSafisChange(x, y []AfiSafi) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Neighbor) NeedsResendOpenMessage(new *Neighbor) bool {
|
||||||
|
return !n.Config.Equal(&new.Config) ||
|
||||||
|
!n.Transport.Config.Equal(&new.Transport.Config) ||
|
||||||
|
!n.AddPaths.Config.Equal(&new.AddPaths.Config) ||
|
||||||
|
!n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) ||
|
||||||
|
isAfiSafiChanged(n.AfiSafis, new.AfiSafis)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: these regexp are duplicated in api
|
||||||
|
var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`)
|
||||||
|
|
||||||
func ParseMaskLength(prefix, mask string) (int, int, error) {
|
func ParseMaskLength(prefix, mask string) (int, int, error) {
|
||||||
_, ipNet, err := net.ParseCIDR(prefix)
|
_, ipNet, err := net.ParseCIDR(prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -241,8 +235,7 @@ func ParseMaskLength(prefix, mask string) (int, int, error) {
|
|||||||
l, _ := ipNet.Mask.Size()
|
l, _ := ipNet.Mask.Size()
|
||||||
return l, l, nil
|
return l, l, nil
|
||||||
}
|
}
|
||||||
exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
|
elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask)
|
||||||
elems := exp.FindStringSubmatch(mask)
|
|
||||||
if len(elems) != 3 {
|
if len(elems) != 3 {
|
||||||
return 0, 0, fmt.Errorf("invalid mask length range: %s", mask)
|
return 0, 0, fmt.Errorf("invalid mask length range: %s", mask)
|
||||||
}
|
}
|
||||||
|
|||||||
31
vendor/github.com/osrg/gobgp/gobgp/cmd/common.go
generated
vendored
31
vendor/github.com/osrg/gobgp/gobgp/cmd/common.go
generated
vendored
@ -29,10 +29,10 @@ import (
|
|||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
|
||||||
|
api "github.com/osrg/gobgp/api"
|
||||||
cli "github.com/osrg/gobgp/client"
|
cli "github.com/osrg/gobgp/client"
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
"github.com/osrg/gobgp/table"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -97,23 +97,6 @@ var neighborsOpts struct {
|
|||||||
Transport string `short:"t" long:"transport" description:"specifying a transport protocol"`
|
Transport string `short:"t" long:"transport" description:"specifying a transport protocol"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var conditionOpts struct {
|
|
||||||
Prefix string `long:"prefix" description:"specifying a prefix set name of policy"`
|
|
||||||
Neighbor string `long:"neighbor" description:"specifying a neighbor set name of policy"`
|
|
||||||
AsPath string `long:"aspath" description:"specifying an as set name of policy"`
|
|
||||||
Community string `long:"community" description:"specifying a community set name of policy"`
|
|
||||||
ExtCommunity string `long:"extcommunity" description:"specifying a extended community set name of policy"`
|
|
||||||
AsPathLength string `long:"aspath-len" description:"specifying an as path length of policy (<operator>,<numeric>)"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var actionOpts struct {
|
|
||||||
RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"`
|
|
||||||
CommunityAction string `long:"community" description:"specifying a community action of policy"`
|
|
||||||
MedAction string `long:"med" description:"specifying a med action of policy"`
|
|
||||||
AsPathPrependAction string `long:"as-prepend" description:"specifying a as-prepend action of policy"`
|
|
||||||
NexthopAction string `long:"next-hop" description:"specifying a next-hop action of policy"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var mrtOpts struct {
|
var mrtOpts struct {
|
||||||
OutputDir string
|
OutputDir string
|
||||||
FileFormat string
|
FileFormat string
|
||||||
@ -142,9 +125,8 @@ func formatTimedelta(d int64) string {
|
|||||||
|
|
||||||
if days == 0 {
|
if days == 0 {
|
||||||
return fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
|
return fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
|
|
||||||
}
|
}
|
||||||
|
return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cidr2prefix(cidr string) string {
|
func cidr2prefix(cidr string) string {
|
||||||
@ -217,10 +199,7 @@ func (n neighbors) Less(i, j int) bool {
|
|||||||
p1Isv4 := !strings.Contains(p1, ":")
|
p1Isv4 := !strings.Contains(p1, ":")
|
||||||
p2Isv4 := !strings.Contains(p2, ":")
|
p2Isv4 := !strings.Contains(p2, ":")
|
||||||
if p1Isv4 != p2Isv4 {
|
if p1Isv4 != p2Isv4 {
|
||||||
if p1Isv4 {
|
return p1Isv4
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
addrlen := 128
|
addrlen := 128
|
||||||
if p1Isv4 {
|
if p1Isv4 {
|
||||||
@ -245,7 +224,7 @@ func (c capabilities) Less(i, j int) bool {
|
|||||||
return c[i].Code() < c[j].Code()
|
return c[i].Code() < c[j].Code()
|
||||||
}
|
}
|
||||||
|
|
||||||
type vrfs []*table.Vrf
|
type vrfs []*api.Vrf
|
||||||
|
|
||||||
func (v vrfs) Len() int {
|
func (v vrfs) Len() int {
|
||||||
return len(v)
|
return len(v)
|
||||||
@ -281,7 +260,7 @@ func newClient() *cli.Client {
|
|||||||
target := net.JoinHostPort(globalOpts.Host, strconv.Itoa(globalOpts.Port))
|
target := net.JoinHostPort(globalOpts.Host, strconv.Itoa(globalOpts.Port))
|
||||||
client, err := cli.New(target, grpcOpts...)
|
client, err := cli.New(target, grpcOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exitWithError(err)
|
exitWithError(fmt.Errorf("failed to connect to %s over gRPC: %s", target, err))
|
||||||
}
|
}
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|||||||
69
vendor/github.com/osrg/gobgp/gobgp/cmd/global.go
generated
vendored
69
vendor/github.com/osrg/gobgp/gobgp/cmd/global.go
generated
vendored
@ -465,22 +465,23 @@ func ParseEvpnEthernetAutoDiscoveryArgs(args []string) (bgp.AddrPrefixInterface,
|
|||||||
|
|
||||||
func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
|
func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
|
||||||
// Format:
|
// Format:
|
||||||
// <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway]
|
// <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway]
|
||||||
// or
|
// or
|
||||||
// <mac address> <ip address> <etag> [esi <esi>] label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway]
|
// <mac address> <ip address> <etag> [esi <esi>] label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway]
|
||||||
// or
|
// or
|
||||||
// <mac address> <ip address> <etag> <label> [esi <esi>] rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway]
|
// <mac address> <ip address> <etag> <label> [esi <esi>] rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway]
|
||||||
req := 6
|
req := 6
|
||||||
if len(args) < req {
|
if len(args) < req {
|
||||||
return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args))
|
return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args))
|
||||||
}
|
}
|
||||||
m, err := extractReserved(args, map[string]int{
|
m, err := extractReserved(args, map[string]int{
|
||||||
"esi": PARAM_LIST,
|
"esi": PARAM_LIST,
|
||||||
"etag": PARAM_SINGLE,
|
"etag": PARAM_SINGLE,
|
||||||
"label": PARAM_SINGLE,
|
"label": PARAM_SINGLE,
|
||||||
"rd": PARAM_SINGLE,
|
"rd": PARAM_SINGLE,
|
||||||
"rt": PARAM_LIST,
|
"rt": PARAM_LIST,
|
||||||
"encap": PARAM_SINGLE})
|
"encap": PARAM_SINGLE,
|
||||||
|
"router-mac": PARAM_SINGLE})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -560,6 +561,15 @@ func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, erro
|
|||||||
if len(m["encap"]) > 0 {
|
if len(m["encap"]) > 0 {
|
||||||
extcomms = append(extcomms, "encap", m["encap"][0])
|
extcomms = append(extcomms, "encap", m["encap"][0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(m["router-mac"]) != 0 {
|
||||||
|
_, err := net.ParseMAC(m["router-mac"][0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("invalid router-mac address: %s", m["router-mac"][0])
|
||||||
|
}
|
||||||
|
extcomms = append(extcomms, "router-mac", m["router-mac"][0])
|
||||||
|
}
|
||||||
|
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
if a == "default-gateway" {
|
if a == "default-gateway" {
|
||||||
extcomms = append(extcomms, "default-gateway")
|
extcomms = append(extcomms, "default-gateway")
|
||||||
@ -867,18 +877,21 @@ func toAs4Value(s string) (uint32, error) {
|
|||||||
return uint32(i), nil
|
return uint32(i), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_regexpASPathGroups = regexp.MustCompile("[{}]")
|
||||||
|
_regexpASPathSegment = regexp.MustCompile(`,|\s+`)
|
||||||
|
)
|
||||||
|
|
||||||
func newAsPath(aspath string) (bgp.PathAttributeInterface, error) {
|
func newAsPath(aspath string) (bgp.PathAttributeInterface, error) {
|
||||||
// For the first step, parses "aspath" into a list of uint32 list.
|
// For the first step, parses "aspath" into a list of uint32 list.
|
||||||
// e.g.) "10 20 {30,40} 50" -> [][]uint32{{10, 20}, {30, 40}, {50}}
|
// e.g.) "10 20 {30,40} 50" -> [][]uint32{{10, 20}, {30, 40}, {50}}
|
||||||
exp := regexp.MustCompile("[{}]")
|
segments := _regexpASPathGroups.Split(aspath, -1)
|
||||||
segments := exp.Split(aspath, -1)
|
|
||||||
asPathPrams := make([]bgp.AsPathParamInterface, 0, len(segments))
|
asPathPrams := make([]bgp.AsPathParamInterface, 0, len(segments))
|
||||||
exp = regexp.MustCompile(",|\\s+")
|
|
||||||
for idx, segment := range segments {
|
for idx, segment := range segments {
|
||||||
if segment == "" {
|
if segment == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nums := exp.Split(segment, -1)
|
nums := _regexpASPathSegment.Split(segment, -1)
|
||||||
asNums := make([]uint32, 0, len(nums))
|
asNums := make([]uint32, 0, len(nums))
|
||||||
for _, n := range nums {
|
for _, n := range nums {
|
||||||
if n == "" {
|
if n == "" {
|
||||||
@ -1061,22 +1074,6 @@ func extractAggregator(args []string) ([]string, bgp.PathAttributeInterface, err
|
|||||||
return args, nil, nil
|
return args, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractRouteDistinguisher(args []string) ([]string, bgp.RouteDistinguisherInterface, error) {
|
|
||||||
for idx, arg := range args {
|
|
||||||
if arg == "rd" {
|
|
||||||
if len(args) < (idx + 1) {
|
|
||||||
return nil, nil, fmt.Errorf("invalid rd format")
|
|
||||||
}
|
|
||||||
rd, err := bgp.ParseRouteDistinguisher(args[idx+1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return append(args[:idx], args[idx+2:]...), rd, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
|
func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
|
||||||
var nlri bgp.AddrPrefixInterface
|
var nlri bgp.AddrPrefixInterface
|
||||||
var extcomms []string
|
var extcomms []string
|
||||||
@ -1148,7 +1145,10 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
|
|||||||
if len(args) < 5 || args[1] != "label" || args[3] != "rd" {
|
if len(args) < 5 || args[1] != "label" || args[3] != "rd" {
|
||||||
return nil, fmt.Errorf("invalid format")
|
return nil, fmt.Errorf("invalid format")
|
||||||
}
|
}
|
||||||
ip, nw, _ := net.ParseCIDR(args[0])
|
ip, nw, err := net.ParseCIDR(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ones, _ := nw.Mask.Size()
|
ones, _ := nw.Mask.Size()
|
||||||
|
|
||||||
label, err := strconv.ParseUint(args[2], 10, 32)
|
label, err := strconv.ParseUint(args[2], 10, 32)
|
||||||
@ -1180,7 +1180,10 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
|
|||||||
return nil, fmt.Errorf("invalid format")
|
return nil, fmt.Errorf("invalid format")
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, nw, _ := net.ParseCIDR(args[0])
|
ip, nw, err := net.ParseCIDR(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ones, _ := nw.Mask.Size()
|
ones, _ := nw.Mask.Size()
|
||||||
|
|
||||||
mpls, err := bgp.ParseMPLSLabelStack(args[1])
|
mpls, err := bgp.ParseMPLSLabelStack(args[1])
|
||||||
@ -1234,7 +1237,7 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
|
|||||||
attrs = append(attrs, mpreach)
|
attrs = append(attrs, mpreach)
|
||||||
}
|
}
|
||||||
|
|
||||||
if extcomms != nil && len(extcomms) > 0 {
|
if extcomms != nil {
|
||||||
extcomms, err := ParseExtendedCommunities(extcomms)
|
extcomms, err := ParseExtendedCommunities(extcomms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1422,7 +1425,7 @@ usage: %s rib -a %%s %s%%s match <MATCH> then <THEN>%%s%%s%%s
|
|||||||
helpErrMap[bgp.RF_EVPN] = fmt.Errorf(`error: %s
|
helpErrMap[bgp.RF_EVPN] = fmt.Errorf(`error: %s
|
||||||
usage: %s rib %s { a-d <A-D> | macadv <MACADV> | multicast <MULTICAST> | esi <ESI> | prefix <PREFIX> } -a evpn
|
usage: %s rib %s { a-d <A-D> | macadv <MACADV> | multicast <MULTICAST> | esi <ESI> | prefix <PREFIX> } -a evpn
|
||||||
<A-D> : esi <esi> etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [esi-label <esi-label> [single-active | all-active]]
|
<A-D> : esi <esi> etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [esi-label <esi-label> [single-active | all-active]]
|
||||||
<MACADV> : <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway]
|
<MACADV> : <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway]
|
||||||
<MULTICAST> : <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] [pmsi <type> [leaf-info-required] <label> <tunnel-id>]
|
<MULTICAST> : <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] [pmsi <type> [leaf-info-required] <label> <tunnel-id>]
|
||||||
<ESI> : <ip address> esi <esi> rd <rd> [rt <rt>...] [encap <encap type>]
|
<ESI> : <ip address> esi <esi> rd <rd> [rt <rt>...] [encap <encap type>]
|
||||||
<PREFIX> : <ip prefix> [gw <gateway>] [esi <esi>] etag <etag> [label <label>] rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>]`,
|
<PREFIX> : <ip prefix> [gw <gateway>] [esi <esi>] etag <etag> [label <label>] rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>]`,
|
||||||
|
|||||||
7
vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go
generated
vendored
7
vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go
generated
vendored
@ -142,11 +142,8 @@ func injectMrt() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if mrtOpts.Best {
|
if mrtOpts.Best {
|
||||||
dst := table.NewDestination(nlri, 0)
|
dst := table.NewDestination(nlri, 0, paths[1:]...)
|
||||||
for _, p := range paths {
|
best, _, _ := dst.Calculate(paths[0]).GetChanges(table.GLOBAL_RIB_NAME, 0, false)
|
||||||
dst.AddNewPath(p)
|
|
||||||
}
|
|
||||||
best, _, _ := dst.Calculate().GetChanges(table.GLOBAL_RIB_NAME, false)
|
|
||||||
if best == nil {
|
if best == nil {
|
||||||
exitWithError(fmt.Errorf("Can't find the best %v", nlri))
|
exitWithError(fmt.Errorf("Can't find the best %v", nlri))
|
||||||
}
|
}
|
||||||
|
|||||||
157
vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go
generated
vendored
157
vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go
generated
vendored
@ -129,11 +129,11 @@ func showNeighbors(vrf string) error {
|
|||||||
}
|
}
|
||||||
timedelta = append(timedelta, timeStr)
|
timedelta = append(timedelta, timeStr)
|
||||||
}
|
}
|
||||||
var format string
|
|
||||||
format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
|
format := "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
|
||||||
format += " %-11s |%9s %9s\n"
|
format += " %-11s |%9s %9s\n"
|
||||||
fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Received", "Accepted")
|
fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Received", "Accepted")
|
||||||
format_fsm := func(admin config.AdminState, fsm config.SessionState) string {
|
formatFsm := func(admin config.AdminState, fsm config.SessionState) string {
|
||||||
switch admin {
|
switch admin {
|
||||||
case config.ADMIN_STATE_DOWN:
|
case config.ADMIN_STATE_DOWN:
|
||||||
return "Idle(Admin)"
|
return "Idle(Admin)"
|
||||||
@ -164,7 +164,7 @@ func showNeighbors(vrf string) error {
|
|||||||
if n.Config.NeighborInterface != "" {
|
if n.Config.NeighborInterface != "" {
|
||||||
neigh = n.Config.NeighborInterface
|
neigh = n.Config.NeighborInterface
|
||||||
}
|
}
|
||||||
fmt.Printf(format, neigh, getASN(n), timedelta[i], format_fsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted))
|
fmt.Printf(format, neigh, getASN(n), timedelta[i], formatFsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -196,7 +196,12 @@ func showNeighbor(args []string) error {
|
|||||||
id = p.State.RemoteRouterId
|
id = p.State.RemoteRouterId
|
||||||
}
|
}
|
||||||
fmt.Printf(" BGP version 4, remote router ID %s\n", id)
|
fmt.Printf(" BGP version 4, remote router ID %s\n", id)
|
||||||
fmt.Printf(" BGP state = %s, up for %s\n", p.State.SessionState, formatTimedelta(int64(p.Timers.State.Uptime)-time.Now().Unix()))
|
fmt.Printf(" BGP state = %s", p.State.SessionState)
|
||||||
|
if p.Timers.State.Uptime > 0 {
|
||||||
|
fmt.Printf(", up for %s\n", formatTimedelta(int64(p.Timers.State.Uptime)-time.Now().Unix()))
|
||||||
|
} else {
|
||||||
|
fmt.Print("\n")
|
||||||
|
}
|
||||||
fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.State.Queues.Output, p.State.Flops)
|
fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.State.Queues.Output, p.State.Flops)
|
||||||
fmt.Printf(" Hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.State.NegotiatedHoldTime), int(p.Timers.State.KeepaliveInterval))
|
fmt.Printf(" Hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.State.NegotiatedHoldTime), int(p.Timers.State.KeepaliveInterval))
|
||||||
fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.Config.HoldTime), int(p.Timers.Config.KeepaliveInterval))
|
fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.Config.HoldTime), int(p.Timers.Config.KeepaliveInterval))
|
||||||
@ -417,11 +422,7 @@ func showNeighbor(args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type AsPathFormat struct {
|
type AsPathFormat struct{}
|
||||||
start string
|
|
||||||
end string
|
|
||||||
separator string
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPathSymbolString(p *table.Path, idx int, showBest bool) string {
|
func getPathSymbolString(p *table.Path, idx int, showBest bool) string {
|
||||||
symbols := ""
|
symbols := ""
|
||||||
@ -701,6 +702,7 @@ func showNeighborRib(r string, name string, args []string) error {
|
|||||||
showAge = false
|
showAge = false
|
||||||
case CMD_VRF:
|
case CMD_VRF:
|
||||||
def = bgp.RF_IPv4_UC
|
def = bgp.RF_IPv4_UC
|
||||||
|
showBest = true
|
||||||
}
|
}
|
||||||
family, err := checkAddressFamily(def)
|
family, err := checkAddressFamily(def)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -768,7 +770,7 @@ func showNeighborRib(r string, name string, args []string) error {
|
|||||||
|
|
||||||
switch r {
|
switch r {
|
||||||
case CMD_LOCAL, CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED, CMD_ADJ_OUT:
|
case CMD_LOCAL, CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED, CMD_ADJ_OUT:
|
||||||
if rib.Info("").NumDestination == 0 {
|
if rib.Info("", 0).NumDestination == 0 {
|
||||||
peer, err := client.GetNeighbor(name, false)
|
peer, err := client.GetNeighbor(name, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -780,14 +782,28 @@ func showNeighborRib(r string, name string, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if globalOpts.Json {
|
if globalOpts.Json {
|
||||||
j, _ := json.Marshal(rib.GetDestinations())
|
d := make(map[string]*table.Destination)
|
||||||
|
for _, dst := range rib.GetDestinations() {
|
||||||
|
d[dst.GetNlri().String()] = dst
|
||||||
|
}
|
||||||
|
j, _ := json.Marshal(d)
|
||||||
fmt.Println(string(j))
|
fmt.Println(string(j))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if validationTarget != "" {
|
if validationTarget != "" {
|
||||||
// show RPKI validation info
|
// show RPKI validation info
|
||||||
d := rib.GetDestination(validationTarget)
|
addr, _, err := net.ParseCIDR(validationTarget)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var nlri bgp.AddrPrefixInterface
|
||||||
|
if addr.To16() == nil {
|
||||||
|
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, validationTarget)
|
||||||
|
} else {
|
||||||
|
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, validationTarget)
|
||||||
|
}
|
||||||
|
d := rib.GetDestination(nlri)
|
||||||
if d == nil {
|
if d == nil {
|
||||||
fmt.Println("Network not in table")
|
fmt.Println("Network not in table")
|
||||||
return nil
|
return nil
|
||||||
@ -805,19 +821,9 @@ func showNeighborRib(r string, name string, args []string) error {
|
|||||||
var ps []*table.Path
|
var ps []*table.Path
|
||||||
switch r {
|
switch r {
|
||||||
case CMD_ACCEPTED:
|
case CMD_ACCEPTED:
|
||||||
for _, p := range d.GetAllKnownPathList() {
|
ps = append(ps, d.GetAllKnownPathList()...)
|
||||||
if p.Filtered("") > table.POLICY_DIRECTION_NONE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ps = append(ps, p)
|
|
||||||
}
|
|
||||||
case CMD_REJECTED:
|
case CMD_REJECTED:
|
||||||
for _, p := range d.GetAllKnownPathList() {
|
// always nothing
|
||||||
if p.Filtered("") == table.POLICY_DIRECTION_NONE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ps = append(ps, p)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
ps = d.GetAllKnownPathList()
|
ps = d.GetAllKnownPathList()
|
||||||
}
|
}
|
||||||
@ -871,8 +877,6 @@ func showNeighborPolicy(remoteIP, policyType string, indent int) error {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch strings.ToLower(policyType) {
|
switch strings.ToLower(policyType) {
|
||||||
case "in":
|
|
||||||
assignment, err = client.GetRouteServerInPolicy(remoteIP)
|
|
||||||
case "import":
|
case "import":
|
||||||
assignment, err = client.GetRouteServerImportPolicy(remoteIP)
|
assignment, err = client.GetRouteServerImportPolicy(remoteIP)
|
||||||
case "export":
|
case "export":
|
||||||
@ -925,8 +929,6 @@ func modNeighborPolicy(remoteIP, policyType, cmdType string, args []string) erro
|
|||||||
Name: remoteIP,
|
Name: remoteIP,
|
||||||
}
|
}
|
||||||
switch strings.ToLower(policyType) {
|
switch strings.ToLower(policyType) {
|
||||||
case "in":
|
|
||||||
assign.Type = table.POLICY_DIRECTION_IN
|
|
||||||
case "import":
|
case "import":
|
||||||
assign.Type = table.POLICY_DIRECTION_IMPORT
|
assign.Type = table.POLICY_DIRECTION_IMPORT
|
||||||
case "export":
|
case "export":
|
||||||
@ -973,9 +975,16 @@ func modNeighborPolicy(remoteIP, policyType, cmdType string, args []string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func modNeighbor(cmdType string, args []string) error {
|
func modNeighbor(cmdType string, args []string) error {
|
||||||
params := map[string]int{"interface": PARAM_SINGLE}
|
params := map[string]int{
|
||||||
|
"interface": PARAM_SINGLE,
|
||||||
|
}
|
||||||
usage := fmt.Sprintf("usage: gobgp neighbor %s [ <neighbor-address> | interface <neighbor-interface> ]", cmdType)
|
usage := fmt.Sprintf("usage: gobgp neighbor %s [ <neighbor-address> | interface <neighbor-interface> ]", cmdType)
|
||||||
if cmdType == CMD_ADD {
|
if cmdType == CMD_ADD {
|
||||||
|
usage += " as <VALUE>"
|
||||||
|
} else if cmdType == CMD_UPDATE {
|
||||||
|
usage += " [ as <VALUE> ]"
|
||||||
|
}
|
||||||
|
if cmdType == CMD_ADD || cmdType == CMD_UPDATE {
|
||||||
params["as"] = PARAM_SINGLE
|
params["as"] = PARAM_SINGLE
|
||||||
params["family"] = PARAM_SINGLE
|
params["family"] = PARAM_SINGLE
|
||||||
params["vrf"] = PARAM_SINGLE
|
params["vrf"] = PARAM_SINGLE
|
||||||
@ -984,13 +993,14 @@ func modNeighbor(cmdType string, args []string) error {
|
|||||||
params["allow-own-as"] = PARAM_SINGLE
|
params["allow-own-as"] = PARAM_SINGLE
|
||||||
params["remove-private-as"] = PARAM_SINGLE
|
params["remove-private-as"] = PARAM_SINGLE
|
||||||
params["replace-peer-as"] = PARAM_FLAG
|
params["replace-peer-as"] = PARAM_FLAG
|
||||||
usage += " as <VALUE> [ family <address-families-list> | vrf <vrf-name> | route-reflector-client [<cluster-id>] | route-server-client | allow-own-as <num> | remove-private-as (all|replace) | replace-peer-as ]"
|
usage += " [ family <address-families-list> | vrf <vrf-name> | route-reflector-client [<cluster-id>] | route-server-client | allow-own-as <num> | remove-private-as (all|replace) | replace-peer-as ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := extractReserved(args, params)
|
m, err := extractReserved(args, params)
|
||||||
if err != nil || (len(m[""]) != 1 && len(m["interface"]) != 1) {
|
if err != nil || (len(m[""]) != 1 && len(m["interface"]) != 1) {
|
||||||
return fmt.Errorf("%s", usage)
|
return fmt.Errorf("%s", usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
unnumbered := len(m["interface"]) > 0
|
unnumbered := len(m["interface"]) > 0
|
||||||
if !unnumbered {
|
if !unnumbered {
|
||||||
if _, err := net.ResolveIPAddr("ip", m[""][0]); err != nil {
|
if _, err := net.ResolveIPAddr("ip", m[""][0]); err != nil {
|
||||||
@ -998,28 +1008,53 @@ func modNeighbor(cmdType string, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getConf := func(asn uint32) (*config.Neighbor, error) {
|
getNeighborAddress := func() (string, error) {
|
||||||
peer := &config.Neighbor{
|
|
||||||
Config: config.NeighborConfig{
|
|
||||||
PeerAs: asn,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if unnumbered {
|
if unnumbered {
|
||||||
peer.Config.NeighborInterface = m["interface"][0]
|
return config.GetIPv6LinkLocalNeighborAddress(m["interface"][0])
|
||||||
addr, err := config.GetIPv6LinkLocalNeighborAddress(peer.Config.NeighborInterface)
|
}
|
||||||
|
return m[""][0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
getNeighborConfig := func() (*config.Neighbor, error) {
|
||||||
|
addr, err := getNeighborAddress()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var peer *config.Neighbor
|
||||||
|
switch cmdType {
|
||||||
|
case CMD_ADD, CMD_DEL:
|
||||||
|
peer = &config.Neighbor{}
|
||||||
|
if unnumbered {
|
||||||
|
peer.Config.NeighborInterface = m["interface"][0]
|
||||||
|
} else {
|
||||||
|
peer.Config.NeighborAddress = addr
|
||||||
|
}
|
||||||
|
peer.State.NeighborAddress = addr
|
||||||
|
case CMD_UPDATE:
|
||||||
|
peer, err = client.GetNeighbor(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
peer.State.NeighborAddress = addr
|
default:
|
||||||
} else {
|
return nil, fmt.Errorf("invalid command: %s", cmdType)
|
||||||
peer.Config.NeighborAddress = m[""][0]
|
}
|
||||||
peer.State.NeighborAddress = m[""][0]
|
return peer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNeighborConfig := func(peer *config.Neighbor) error {
|
||||||
|
if len(m["as"]) > 0 {
|
||||||
|
as, err := strconv.ParseUint(m["as"][0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
peer.Config.PeerAs = uint32(as)
|
||||||
}
|
}
|
||||||
if len(m["family"]) == 1 {
|
if len(m["family"]) == 1 {
|
||||||
|
peer.AfiSafis = make([]config.AfiSafi, 0) // for the case of CMD_UPDATE
|
||||||
for _, family := range strings.Split(m["family"][0], ",") {
|
for _, family := range strings.Split(m["family"][0], ",") {
|
||||||
afiSafiName := config.AfiSafiType(family)
|
afiSafiName := config.AfiSafiType(family)
|
||||||
if afiSafiName.ToInt() == -1 {
|
if afiSafiName.ToInt() == -1 {
|
||||||
return nil, fmt.Errorf("invalid family value: %s", family)
|
return fmt.Errorf("invalid family value: %s", family)
|
||||||
}
|
}
|
||||||
peer.AfiSafis = append(peer.AfiSafis, config.AfiSafi{Config: config.AfiSafiConfig{AfiSafiName: afiSafiName}})
|
peer.AfiSafis = append(peer.AfiSafis, config.AfiSafi{Config: config.AfiSafiConfig{AfiSafiName: afiSafiName}})
|
||||||
}
|
}
|
||||||
@ -1027,12 +1062,12 @@ func modNeighbor(cmdType string, args []string) error {
|
|||||||
if len(m["vrf"]) == 1 {
|
if len(m["vrf"]) == 1 {
|
||||||
peer.Config.Vrf = m["vrf"][0]
|
peer.Config.Vrf = m["vrf"][0]
|
||||||
}
|
}
|
||||||
if rr, ok := m["route-reflector-client"]; ok {
|
if option, ok := m["route-reflector-client"]; ok {
|
||||||
peer.RouteReflector.Config = config.RouteReflectorConfig{
|
peer.RouteReflector.Config = config.RouteReflectorConfig{
|
||||||
RouteReflectorClient: true,
|
RouteReflectorClient: true,
|
||||||
}
|
}
|
||||||
if len(rr) == 1 {
|
if len(option) == 1 {
|
||||||
peer.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(rr[0])
|
peer.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(option[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := m["route-server-client"]; ok {
|
if _, ok := m["route-server-client"]; ok {
|
||||||
@ -1043,7 +1078,7 @@ func modNeighbor(cmdType string, args []string) error {
|
|||||||
if option, ok := m["allow-own-as"]; ok {
|
if option, ok := m["allow-own-as"]; ok {
|
||||||
as, err := strconv.ParseUint(option[0], 10, 8)
|
as, err := strconv.ParseUint(option[0], 10, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
peer.AsPathOptions.Config.AllowOwnAs = uint8(as)
|
peer.AsPathOptions.Config.AllowOwnAs = uint8(as)
|
||||||
}
|
}
|
||||||
@ -1054,36 +1089,34 @@ func modNeighbor(cmdType string, args []string) error {
|
|||||||
case "replace":
|
case "replace":
|
||||||
peer.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_REPLACE
|
peer.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_REPLACE
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid remove-private-as value: all or replace")
|
return fmt.Errorf("invalid remove-private-as value: all or replace")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := m["replace-peer-as"]; ok {
|
if _, ok := m["replace-peer-as"]; ok {
|
||||||
peer.AsPathOptions.Config.ReplacePeerAs = true
|
peer.AsPathOptions.Config.ReplacePeerAs = true
|
||||||
}
|
}
|
||||||
return peer, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var as uint64
|
n, err := getNeighborConfig()
|
||||||
if len(m["as"]) > 0 {
|
|
||||||
var err error
|
|
||||||
if as, err = strconv.ParseUint(m["as"][0], 10, 32); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := getConf(uint32(as))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cmdType {
|
switch cmdType {
|
||||||
case CMD_ADD:
|
case CMD_ADD:
|
||||||
if len(m[""]) > 0 && len(m["as"]) != 1 {
|
if err := updateNeighborConfig(n); err != nil {
|
||||||
return fmt.Errorf("%s", usage)
|
return err
|
||||||
}
|
}
|
||||||
return client.AddNeighbor(n)
|
return client.AddNeighbor(n)
|
||||||
case CMD_DEL:
|
case CMD_DEL:
|
||||||
return client.DeleteNeighbor(n)
|
return client.DeleteNeighbor(n)
|
||||||
|
case CMD_UPDATE:
|
||||||
|
if err := updateNeighborConfig(n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := client.UpdateNeighbor(n, true)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1219,7 +1252,7 @@ func NewNeighborCmd() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range []string{CMD_ADD, CMD_DEL} {
|
for _, v := range []string{CMD_ADD, CMD_DEL, CMD_UPDATE} {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: v,
|
Use: v,
|
||||||
Run: func(c *cobra.Command, args []string) {
|
Run: func(c *cobra.Command, args []string) {
|
||||||
|
|||||||
30
vendor/github.com/osrg/gobgp/gobgp/cmd/policy.go
generated
vendored
30
vendor/github.com/osrg/gobgp/gobgp/cmd/policy.go
generated
vendored
@ -31,6 +31,8 @@ import (
|
|||||||
"github.com/osrg/gobgp/table"
|
"github.com/osrg/gobgp/table"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _regexpCommunity = regexp.MustCompile(`\^\^(\S+)\$\$`)
|
||||||
|
|
||||||
func formatDefinedSet(head bool, typ string, indent int, list []table.DefinedSet) string {
|
func formatDefinedSet(head bool, typ string, indent int, list []table.DefinedSet) string {
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
return "Nothing defined yet\n"
|
return "Nothing defined yet\n"
|
||||||
@ -59,13 +61,12 @@ func formatDefinedSet(head bool, typ string, indent int, list []table.DefinedSet
|
|||||||
}
|
}
|
||||||
for i, x := range l {
|
for i, x := range l {
|
||||||
if typ == "COMMUNITY" || typ == "EXT-COMMUNITY" || typ == "LARGE-COMMUNITY" {
|
if typ == "COMMUNITY" || typ == "EXT-COMMUNITY" || typ == "LARGE-COMMUNITY" {
|
||||||
exp := regexp.MustCompile("\\^\\^(\\S+)\\$\\$")
|
x = _regexpCommunity.ReplaceAllString(x, "$1")
|
||||||
x = exp.ReplaceAllString(x, "$1")
|
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
buff.WriteString(fmt.Sprintf(format, s.Name(), x))
|
buff.WriteString(fmt.Sprintf(format, s.Name(), x))
|
||||||
} else {
|
} else {
|
||||||
buff.WriteString(fmt.Sprintf(sIndent))
|
buff.WriteString(fmt.Sprint(sIndent))
|
||||||
buff.WriteString(fmt.Sprintf(format, "", x))
|
buff.WriteString(fmt.Sprintf(format, "", x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,12 +334,16 @@ func printStatement(indent int, s *table.Statement) {
|
|||||||
fmt.Printf("%sExtCommunitySet: %s %s\n", ind, t.Option(), t.Name())
|
fmt.Printf("%sExtCommunitySet: %s %s\n", ind, t.Option(), t.Name())
|
||||||
case *table.LargeCommunityCondition:
|
case *table.LargeCommunityCondition:
|
||||||
fmt.Printf("%sLargeCommunitySet: %s %s\n", ind, t.Option(), t.Name())
|
fmt.Printf("%sLargeCommunitySet: %s %s\n", ind, t.Option(), t.Name())
|
||||||
|
case *table.NextHopCondition:
|
||||||
|
fmt.Printf("%sNextHopInList: %s\n", ind, t.String())
|
||||||
case *table.AsPathLengthCondition:
|
case *table.AsPathLengthCondition:
|
||||||
fmt.Printf("%sAsPathLength: %s\n", ind, t.String())
|
fmt.Printf("%sAsPathLength: %s\n", ind, t.String())
|
||||||
case *table.RpkiValidationCondition:
|
case *table.RpkiValidationCondition:
|
||||||
fmt.Printf("%sRPKI result: %s\n", ind, t.String())
|
fmt.Printf("%sRPKI result: %s\n", ind, t.String())
|
||||||
case *table.RouteTypeCondition:
|
case *table.RouteTypeCondition:
|
||||||
fmt.Printf("%sRoute Type: %s\n", ind, t.String())
|
fmt.Printf("%sRoute Type: %s\n", ind, t.String())
|
||||||
|
case *table.AfiSafiInCondition:
|
||||||
|
fmt.Printf("%sAFI SAFI In: %s\n", ind, t.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +485,7 @@ func modCondition(name, op string, args []string) error {
|
|||||||
}
|
}
|
||||||
usage := fmt.Sprintf("usage: gobgp policy statement %s %s condition", name, op)
|
usage := fmt.Sprintf("usage: gobgp policy statement %s %s condition", name, op)
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage)
|
return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type | next-hop-in-list | afi-safi-in }", usage)
|
||||||
}
|
}
|
||||||
typ := args[0]
|
typ := args[0]
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
@ -637,8 +642,20 @@ func modCondition(name, op string, args []string) error {
|
|||||||
default:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "next-hop-in-list":
|
||||||
|
stmt.Conditions.BgpConditions.NextHopInList = args
|
||||||
|
case "afi-safi-in":
|
||||||
|
afiSafisInList := make([]config.AfiSafiType, 0, len(args))
|
||||||
|
for _, arg := range args {
|
||||||
|
afiSafi := config.AfiSafiType(arg)
|
||||||
|
if err := afiSafi.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
afiSafisInList = append(afiSafisInList, afiSafi)
|
||||||
|
}
|
||||||
|
stmt.Conditions.BgpConditions.AfiSafiInList = afiSafisInList
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage)
|
return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type | next-hop-in-list | afi-safi-in }", usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := table.NewStatement(stmt)
|
t, err := table.NewStatement(stmt)
|
||||||
@ -762,6 +779,9 @@ func modAction(name, op string, args []string) error {
|
|||||||
stmt.Actions.BgpActions.SetNextHop = config.BgpNextHopType(args[0])
|
stmt.Actions.BgpActions.SetNextHop = config.BgpNextHopType(args[0])
|
||||||
}
|
}
|
||||||
t, err := table.NewStatement(stmt)
|
t, err := table.NewStatement(stmt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
switch op {
|
switch op {
|
||||||
case CMD_ADD:
|
case CMD_ADD:
|
||||||
err = client.AddStatement(t)
|
err = client.AddStatement(t)
|
||||||
|
|||||||
1
vendor/github.com/osrg/gobgp/gobgp/cmd/root.go
generated
vendored
1
vendor/github.com/osrg/gobgp/gobgp/cmd/root.go
generated
vendored
@ -37,7 +37,6 @@ var globalOpts struct {
|
|||||||
CaFile string
|
CaFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmds []string
|
|
||||||
var client *cli.Client
|
var client *cli.Client
|
||||||
|
|
||||||
func NewRootCmd() *cobra.Command {
|
func NewRootCmd() *cobra.Command {
|
||||||
|
|||||||
49
vendor/github.com/osrg/gobgp/gobgp/cmd/rpki.go
generated
vendored
49
vendor/github.com/osrg/gobgp/gobgp/cmd/rpki.go
generated
vendored
@ -36,36 +36,37 @@ func showRPKIServer(args []string) error {
|
|||||||
for _, r := range servers {
|
for _, r := range servers {
|
||||||
s := "Down"
|
s := "Down"
|
||||||
uptime := "never"
|
uptime := "never"
|
||||||
if r.State.Up == true {
|
if r.State.Up {
|
||||||
s = "Up"
|
s = "Up"
|
||||||
uptime = fmt.Sprint(formatTimedelta(int64(time.Now().Sub(time.Unix(r.State.Uptime, 0)).Seconds())))
|
uptime = fmt.Sprint(formatTimedelta(int64(time.Since(time.Unix(r.State.Uptime, 0)).Seconds())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(format, net.JoinHostPort(r.Config.Address, fmt.Sprintf("%d", r.Config.Port)), s, uptime, fmt.Sprintf("%d/%d", r.State.RecordsV4, r.State.RecordsV6))
|
fmt.Printf(format, net.JoinHostPort(r.Config.Address, fmt.Sprintf("%d", r.Config.Port)), s, uptime, fmt.Sprintf("%d/%d", r.State.RecordsV4, r.State.RecordsV6))
|
||||||
}
|
}
|
||||||
} else {
|
return nil
|
||||||
for _, r := range servers {
|
}
|
||||||
if r.Config.Address == args[0] {
|
|
||||||
up := "Down"
|
for _, r := range servers {
|
||||||
if r.State.Up == true {
|
if r.Config.Address == args[0] {
|
||||||
up = "Up"
|
up := "Down"
|
||||||
}
|
if r.State.Up {
|
||||||
fmt.Printf("Session: %s, State: %s\n", r.Config.Address, up)
|
up = "Up"
|
||||||
fmt.Println(" Port:", r.Config.Port)
|
|
||||||
fmt.Println(" Serial:", r.State.SerialNumber)
|
|
||||||
fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixesV4, r.State.PrefixesV6)
|
|
||||||
fmt.Printf(" Record: %d/%d\n", r.State.RecordsV4, r.State.RecordsV6)
|
|
||||||
fmt.Println(" Message statistics:")
|
|
||||||
fmt.Printf(" Receivedv4: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix)
|
|
||||||
fmt.Printf(" Receivedv6: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix)
|
|
||||||
fmt.Printf(" SerialNotify: %10d\n", r.State.RpkiMessages.RpkiReceived.SerialNotify)
|
|
||||||
fmt.Printf(" CacheReset: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheReset)
|
|
||||||
fmt.Printf(" CacheResponse: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheResponse)
|
|
||||||
fmt.Printf(" EndOfData: %10d\n", r.State.RpkiMessages.RpkiReceived.EndOfData)
|
|
||||||
fmt.Printf(" Error: %10d\n", r.State.RpkiMessages.RpkiReceived.Error)
|
|
||||||
fmt.Printf(" SerialQuery: %10d\n", r.State.RpkiMessages.RpkiSent.SerialQuery)
|
|
||||||
fmt.Printf(" ResetQuery: %10d\n", r.State.RpkiMessages.RpkiSent.ResetQuery)
|
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Session: %s, State: %s\n", r.Config.Address, up)
|
||||||
|
fmt.Println(" Port:", r.Config.Port)
|
||||||
|
fmt.Println(" Serial:", r.State.SerialNumber)
|
||||||
|
fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixesV4, r.State.PrefixesV6)
|
||||||
|
fmt.Printf(" Record: %d/%d\n", r.State.RecordsV4, r.State.RecordsV6)
|
||||||
|
fmt.Println(" Message statistics:")
|
||||||
|
fmt.Printf(" Receivedv4: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix)
|
||||||
|
fmt.Printf(" Receivedv6: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix)
|
||||||
|
fmt.Printf(" SerialNotify: %10d\n", r.State.RpkiMessages.RpkiReceived.SerialNotify)
|
||||||
|
fmt.Printf(" CacheReset: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheReset)
|
||||||
|
fmt.Printf(" CacheResponse: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheResponse)
|
||||||
|
fmt.Printf(" EndOfData: %10d\n", r.State.RpkiMessages.RpkiReceived.EndOfData)
|
||||||
|
fmt.Printf(" Error: %10d\n", r.State.RpkiMessages.RpkiReceived.Error)
|
||||||
|
fmt.Printf(" SerialQuery: %10d\n", r.State.RpkiMessages.RpkiSent.SerialQuery)
|
||||||
|
fmt.Printf(" ResetQuery: %10d\n", r.State.RpkiMessages.RpkiSent.ResetQuery)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
39
vendor/github.com/osrg/gobgp/gobgp/cmd/vrf.go
generated
vendored
39
vendor/github.com/osrg/gobgp/gobgp/cmd/vrf.go
generated
vendored
@ -22,9 +22,11 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
api "github.com/osrg/gobgp/api"
|
||||||
|
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getVrfs() (vrfs, error) {
|
func getVrfs() (vrfs, error) {
|
||||||
@ -56,21 +58,35 @@ func showVrfs() error {
|
|||||||
lines := make([][]string, 0, len(vrfs))
|
lines := make([][]string, 0, len(vrfs))
|
||||||
for _, v := range vrfs {
|
for _, v := range vrfs {
|
||||||
name := v.Name
|
name := v.Name
|
||||||
rd := v.Rd.String()
|
rd, err := api.UnmarshalRD(v.Rd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rdStr := rd.String()
|
||||||
|
|
||||||
f := func(rts []bgp.ExtendedCommunityInterface) (string, error) {
|
f := func(rts []*any.Any) (string, error) {
|
||||||
ret := make([]string, 0, len(rts))
|
ret := make([]string, 0, len(rts))
|
||||||
for _, rt := range rts {
|
for _, an := range rts {
|
||||||
|
rt, err := api.UnmarshalRT(an)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
ret = append(ret, rt.String())
|
ret = append(ret, rt.String())
|
||||||
}
|
}
|
||||||
return strings.Join(ret, ", "), nil
|
return strings.Join(ret, ", "), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
importRts, _ := f(v.ImportRt)
|
importRts, err := f(v.ImportRt)
|
||||||
exportRts, _ := f(v.ExportRt)
|
if err != nil {
|
||||||
lines = append(lines, []string{name, rd, importRts, exportRts, fmt.Sprintf("%d", v.Id)})
|
return err
|
||||||
|
}
|
||||||
|
exportRts, err := f(v.ExportRt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lines = append(lines, []string{name, rdStr, importRts, exportRts, fmt.Sprintf("%d", v.Id)})
|
||||||
|
|
||||||
for i, v := range []int{len(name), len(rd), len(importRts), len(exportRts)} {
|
for i, v := range []int{len(name), len(rdStr), len(importRts), len(exportRts)} {
|
||||||
if v > maxLens[i] {
|
if v > maxLens[i] {
|
||||||
maxLens[i] = v + 4
|
maxLens[i] = v + 4
|
||||||
}
|
}
|
||||||
@ -137,7 +153,9 @@ func modVrf(typ string, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = client.AddVRF(name, int(id), rd, importRt, exportRt)
|
if err := client.AddVRF(name, int(id), rd, importRt, exportRt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case CMD_DEL:
|
case CMD_DEL:
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return fmt.Errorf("Usage: gobgp vrf del <vrf name>")
|
return fmt.Errorf("Usage: gobgp vrf del <vrf name>")
|
||||||
@ -148,7 +166,6 @@ func modVrf(typ string, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewVrfCmd() *cobra.Command {
|
func NewVrfCmd() *cobra.Command {
|
||||||
|
|
||||||
ribCmd := &cobra.Command{
|
ribCmd := &cobra.Command{
|
||||||
Use: CMD_RIB,
|
Use: CMD_RIB,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|||||||
253
vendor/github.com/osrg/gobgp/packet/bgp/bgp.go
generated
vendored
253
vendor/github.com/osrg/gobgp/packet/bgp/bgp.go
generated
vendored
@ -263,8 +263,8 @@ const (
|
|||||||
BGP_CAP_FOUR_OCTET_AS_NUMBER BGPCapabilityCode = 65
|
BGP_CAP_FOUR_OCTET_AS_NUMBER BGPCapabilityCode = 65
|
||||||
BGP_CAP_ADD_PATH BGPCapabilityCode = 69
|
BGP_CAP_ADD_PATH BGPCapabilityCode = 69
|
||||||
BGP_CAP_ENHANCED_ROUTE_REFRESH BGPCapabilityCode = 70
|
BGP_CAP_ENHANCED_ROUTE_REFRESH BGPCapabilityCode = 70
|
||||||
|
BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 71
|
||||||
BGP_CAP_ROUTE_REFRESH_CISCO BGPCapabilityCode = 128
|
BGP_CAP_ROUTE_REFRESH_CISCO BGPCapabilityCode = 128
|
||||||
BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 129
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var CapNameMap = map[BGPCapabilityCode]string{
|
var CapNameMap = map[BGPCapabilityCode]string{
|
||||||
@ -287,6 +287,51 @@ func (c BGPCapabilityCode) String() string {
|
|||||||
return fmt.Sprintf("UnknownCapability(%d)", c)
|
return fmt.Sprintf("UnknownCapability(%d)", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used parsing RouteDistinguisher
|
||||||
|
_regexpRouteDistinguisher = regexp.MustCompile(`^((\d+)\.(\d+)\.(\d+)\.(\d+)|((\d+)\.)?(\d+)|([\w]+:[\w:]*:[\w]+)):(\d+)$`)
|
||||||
|
|
||||||
|
// Used for operator and value for the FlowSpec numeric type
|
||||||
|
// Example:
|
||||||
|
// re.FindStringSubmatch("&==80")
|
||||||
|
// >>> ["&==80" "&" "==" "80"]
|
||||||
|
_regexpFlowSpecNumericType = regexp.MustCompile(`(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\d+|-\d|true|false)`)
|
||||||
|
|
||||||
|
// - "=!" is used in the old style format of "tcp-flags" and "fragment".
|
||||||
|
// - The value field should be one of the followings:
|
||||||
|
// * Decimal value (e.g., 80)
|
||||||
|
// * Combination of the small letters, decimals, "-" and "+"
|
||||||
|
// (e.g., tcp, ipv4, is-fragment+first-fragment)
|
||||||
|
// * Capital letters (e.g., SA)
|
||||||
|
_regexpFlowSpecOperator = regexp.MustCompile(`&|=|>|<|!|[\w\-+]+`)
|
||||||
|
_regexpFlowSpecOperatorValue = regexp.MustCompile(`[\w\-+]+`)
|
||||||
|
|
||||||
|
// Note: "(-*)" and "(.*)" catch the invalid flags
|
||||||
|
// Example: In this case, "Z" is unsupported flag type.
|
||||||
|
// re.FindStringSubmatch("&==-SZU")
|
||||||
|
// >>> ["&==-SZU" "&" "==" "-" "S" "ZU"]
|
||||||
|
_regexpFlowSpecTCPFlag = regexp.MustCompile("(&?)(==|=|!|!=|=!)?(-*)([FSRPAUCE]+)(.*)")
|
||||||
|
|
||||||
|
// Note: "(.*)" catches the invalid flags
|
||||||
|
// re.FindStringSubmatch("&!=+first-fragment+last-fragment+invalid-fragment")
|
||||||
|
// >>> ["&!=+first-fragment+last-fragment+invalid-fragment" "&" "!=" "+first-fragment+last-fragment" "+last-fragment" "+" "last" "+invalid-fragment"]
|
||||||
|
_regexpFlowSpecFragment = regexp.MustCompile(`(&?)(==|=|!|!=|=!)?(((\+)?(dont|is|first|last|not-a)-fragment)+)(.*)`)
|
||||||
|
|
||||||
|
// re.FindStringSubmatch("192.168.0.0/24")
|
||||||
|
// >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"]
|
||||||
|
// re.FindStringSubmatch("192.168.0.1")
|
||||||
|
// >>> ["192.168.0.1" "192.168.0.1" "" ""]
|
||||||
|
_regexpFindIPv4Prefix = regexp.MustCompile(`^([\d.]+)(/(\d{1,2}))?`)
|
||||||
|
|
||||||
|
// re.FindStringSubmatch("2001:dB8::/64")
|
||||||
|
// >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""]
|
||||||
|
// re.FindStringSubmatch("2001:dB8::/64/8")
|
||||||
|
// >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"]
|
||||||
|
// re.FindStringSubmatch("2001:dB8::1")
|
||||||
|
// >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""]
|
||||||
|
_regexpFindIPv6Prefix = regexp.MustCompile(`^([a-fA-F\d:.]+)(/(\d{1,3}))?(/(\d{1,3}))?`)
|
||||||
|
)
|
||||||
|
|
||||||
type ParameterCapabilityInterface interface {
|
type ParameterCapabilityInterface interface {
|
||||||
DecodeFromBytes([]byte) error
|
DecodeFromBytes([]byte) error
|
||||||
Serialize() ([]byte, error)
|
Serialize() ([]byte, error)
|
||||||
@ -388,6 +433,14 @@ type CapCarryingLabelInfo struct {
|
|||||||
DefaultParameterCapability
|
DefaultParameterCapability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewCapCarryingLabelInfo() *CapCarryingLabelInfo {
|
||||||
|
return &CapCarryingLabelInfo{
|
||||||
|
DefaultParameterCapability{
|
||||||
|
CapCode: BGP_CAP_CARRYING_LABEL_INFO,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type CapExtendedNexthopTuple struct {
|
type CapExtendedNexthopTuple struct {
|
||||||
NLRIAFI uint16
|
NLRIAFI uint16
|
||||||
NLRISAFI uint16
|
NLRISAFI uint16
|
||||||
@ -836,6 +889,15 @@ type CapUnknown struct {
|
|||||||
DefaultParameterCapability
|
DefaultParameterCapability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewCapUnknown(code BGPCapabilityCode, value []byte) *CapUnknown {
|
||||||
|
return &CapUnknown{
|
||||||
|
DefaultParameterCapability{
|
||||||
|
CapCode: code,
|
||||||
|
CapValue: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) {
|
func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) {
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
||||||
return nil, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all ParameterCapability bytes available")
|
return nil, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all ParameterCapability bytes available")
|
||||||
@ -942,6 +1004,9 @@ type BGPOpen struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (msg *BGPOpen) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
|
func (msg *BGPOpen) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
|
||||||
|
if len(data) < 10 {
|
||||||
|
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Not all BGP Open message bytes available")
|
||||||
|
}
|
||||||
msg.Version = data[0]
|
msg.Version = data[0]
|
||||||
msg.MyAS = binary.BigEndian.Uint16(data[1:3])
|
msg.MyAS = binary.BigEndian.Uint16(data[1:3])
|
||||||
msg.HoldTime = binary.BigEndian.Uint16(data[3:5])
|
msg.HoldTime = binary.BigEndian.Uint16(data[3:5])
|
||||||
@ -1427,8 +1492,7 @@ func GetRouteDistinguisher(data []byte) RouteDistinguisherInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseRdAndRt(input string) ([]string, error) {
|
func parseRdAndRt(input string) ([]string, error) {
|
||||||
exp := regexp.MustCompile("^((\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)|((\\d+)\\.)?(\\d+)|([\\w]+:[\\w:]*:[\\w]+)):(\\d+)$")
|
elems := _regexpRouteDistinguisher.FindStringSubmatch(input)
|
||||||
elems := exp.FindStringSubmatch(input)
|
|
||||||
if len(elems) != 11 {
|
if len(elems) != 11 {
|
||||||
return nil, fmt.Errorf("failed to parse")
|
return nil, fmt.Errorf("failed to parse")
|
||||||
}
|
}
|
||||||
@ -1508,7 +1572,8 @@ func (l *MPLSLabelStack) DecodeFromBytes(data []byte) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if foundBottom == false {
|
|
||||||
|
if !foundBottom {
|
||||||
l.Labels = []uint32{}
|
l.Labels = []uint32{}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1785,13 +1850,13 @@ func (l *LabeledIPAddrPrefix) DecodeFromBytes(data []byte, options ...*Marshalli
|
|||||||
l.Length = uint8(data[0])
|
l.Length = uint8(data[0])
|
||||||
data = data[1:]
|
data = data[1:]
|
||||||
l.Labels.DecodeFromBytes(data)
|
l.Labels.DecodeFromBytes(data)
|
||||||
|
|
||||||
if int(l.Length)-8*(l.Labels.Len()) < 0 {
|
if int(l.Length)-8*(l.Labels.Len()) < 0 {
|
||||||
l.Labels.Labels = []uint32{}
|
l.Labels.Labels = []uint32{}
|
||||||
}
|
}
|
||||||
restbits := int(l.Length) - 8*(l.Labels.Len())
|
restbits := int(l.Length) - 8*(l.Labels.Len())
|
||||||
data = data[l.Labels.Len():]
|
data = data[l.Labels.Len():]
|
||||||
l.decodePrefix(data, uint8(restbits), l.addrlen)
|
return l.decodePrefix(data, uint8(restbits), l.addrlen)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LabeledIPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) {
|
func (l *LabeledIPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) {
|
||||||
@ -1891,7 +1956,7 @@ func (n *RouteTargetMembershipNLRI) DecodeFromBytes(data []byte, options ...*Mar
|
|||||||
return NewMessageError(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST), nil, "prefix misses length field")
|
return NewMessageError(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST), nil, "prefix misses length field")
|
||||||
}
|
}
|
||||||
n.Length = data[0]
|
n.Length = data[0]
|
||||||
data = data[1:]
|
data = data[1 : n.Length/8+1]
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil
|
return nil
|
||||||
} else if len(data) != 12 {
|
} else if len(data) != 12 {
|
||||||
@ -1920,7 +1985,7 @@ func (n *RouteTargetMembershipNLRI) Serialize(options ...*MarshallingOption) ([]
|
|||||||
}
|
}
|
||||||
offset := len(buf)
|
offset := len(buf)
|
||||||
buf = append(buf, make([]byte, 5)...)
|
buf = append(buf, make([]byte, 5)...)
|
||||||
buf[offset] = 12 * 8
|
buf[offset] = 96
|
||||||
binary.BigEndian.PutUint32(buf[offset+1:], n.AS)
|
binary.BigEndian.PutUint32(buf[offset+1:], n.AS)
|
||||||
ebuf, err := n.RouteTarget.Serialize()
|
ebuf, err := n.RouteTarget.Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2097,7 +2162,7 @@ func ParseEthernetSegmentIdentifier(args []string) (EthernetSegmentIdentifier, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
invalidEsiValuesError := fmt.Errorf("invalid esi values for type %s: %s", esi.Type.String(), args[1:])
|
invalidEsiValuesError := fmt.Errorf("invalid esi values for type %s: %s", esi.Type.String(), args[1:])
|
||||||
esi.Value = make([]byte, 9, 9)
|
esi.Value = make([]byte, 9)
|
||||||
switch esi.Type {
|
switch esi.Type {
|
||||||
case ESI_LACP:
|
case ESI_LACP:
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -2132,7 +2197,7 @@ func ParseEthernetSegmentIdentifier(args []string) (EthernetSegmentIdentifier, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return esi, invalidEsiValuesError
|
return esi, invalidEsiValuesError
|
||||||
}
|
}
|
||||||
iBuf := make([]byte, 4, 4)
|
iBuf := make([]byte, 4)
|
||||||
binary.BigEndian.PutUint32(iBuf, uint32(i))
|
binary.BigEndian.PutUint32(iBuf, uint32(i))
|
||||||
copy(esi.Value[6:9], iBuf[1:4])
|
copy(esi.Value[6:9], iBuf[1:4])
|
||||||
case ESI_ROUTERID:
|
case ESI_ROUTERID:
|
||||||
@ -2214,7 +2279,7 @@ func labelSerialize(label uint32) ([]byte, error) {
|
|||||||
if label > 0xffffff {
|
if label > 0xffffff {
|
||||||
return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Out of range Label: %d", label))
|
return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Out of range Label: %d", label))
|
||||||
}
|
}
|
||||||
buf := make([]byte, 3, 3)
|
buf := make([]byte, 3)
|
||||||
buf[0] = byte((label >> 16) & 0xff)
|
buf[0] = byte((label >> 16) & 0xff)
|
||||||
buf[1] = byte((label >> 8) & 0xff)
|
buf[1] = byte((label >> 8) & 0xff)
|
||||||
buf[2] = byte(label & 0xff)
|
buf[2] = byte(label & 0xff)
|
||||||
@ -3139,22 +3204,12 @@ var FlowSpecValueMap = map[string]BGPFlowSpecType{
|
|||||||
// fmt.Printf("%q", normalizeFlowSpecOpValues(args))
|
// fmt.Printf("%q", normalizeFlowSpecOpValues(args))
|
||||||
// >>> ["<=80" "tcp" "!=udp" "=!SA" "&=U" "!F" "=is-fragment+last-fragment"]
|
// >>> ["<=80" "tcp" "!=udp" "=!SA" "&=U" "!F" "=is-fragment+last-fragment"]
|
||||||
func normalizeFlowSpecOpValues(args []string) []string {
|
func normalizeFlowSpecOpValues(args []string) []string {
|
||||||
// Note:
|
|
||||||
// - "=!" is used in the old style format of "tcp-flags" and "fragment".
|
|
||||||
// - The value field should be one of the followings:
|
|
||||||
// * Decimal value (e.g., 80)
|
|
||||||
// * Combination of the small letters, decimals, "-" and "+"
|
|
||||||
// (e.g., tcp, ipv4, is-fragment+first-fragment)
|
|
||||||
// * Capital letters (e.g., SA)
|
|
||||||
re := regexp.MustCompile("&|=|>|<|!|[\\w\\-+]+")
|
|
||||||
reValue := regexp.MustCompile("[\\w\\-+]+")
|
|
||||||
|
|
||||||
// Extracts keywords from the given args.
|
// Extracts keywords from the given args.
|
||||||
sub := ""
|
sub := ""
|
||||||
subs := make([]string, 0)
|
subs := make([]string, 0)
|
||||||
for _, s := range re.FindAllString(strings.Join(args, " "), -1) {
|
for _, s := range _regexpFlowSpecOperator.FindAllString(strings.Join(args, " "), -1) {
|
||||||
sub += s
|
sub += s
|
||||||
if reValue.MatchString(s) {
|
if _regexpFlowSpecOperatorValue.MatchString(s) {
|
||||||
subs = append(subs, sub)
|
subs = append(subs, sub)
|
||||||
sub = ""
|
sub = ""
|
||||||
}
|
}
|
||||||
@ -3192,12 +3247,8 @@ func parseFlowSpecNumericOperator(submatch []string) (operator uint8, err error)
|
|||||||
func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(uint64) error) (FlowSpecComponentInterface, error) {
|
func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(uint64) error) (FlowSpecComponentInterface, error) {
|
||||||
argsLen := len(args)
|
argsLen := len(args)
|
||||||
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
||||||
re := regexp.MustCompile("(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\\d+|-\\d|true|false)")
|
|
||||||
for idx, arg := range args {
|
for idx, arg := range args {
|
||||||
// Example:
|
m := _regexpFlowSpecNumericType.FindStringSubmatch(arg)
|
||||||
// re.FindStringSubmatch("&==80")
|
|
||||||
// >>> ["&==80" "&" "==" "80"]
|
|
||||||
m := re.FindStringSubmatch(arg)
|
|
||||||
if len(m) < 4 {
|
if len(m) < 4 {
|
||||||
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
||||||
}
|
}
|
||||||
@ -3295,12 +3346,7 @@ func flowSpecPrefixParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (F
|
|||||||
return nil, fmt.Errorf("cannot specify offset for ipv4 prefix")
|
return nil, fmt.Errorf("cannot specify offset for ipv4 prefix")
|
||||||
}
|
}
|
||||||
invalidIPv4PrefixError := fmt.Errorf("invalid ipv4 prefix: %s", args[0])
|
invalidIPv4PrefixError := fmt.Errorf("invalid ipv4 prefix: %s", args[0])
|
||||||
re := regexp.MustCompile("^([\\d.]+)(/(\\d{1,2}))?")
|
m := _regexpFindIPv4Prefix.FindStringSubmatch(args[0])
|
||||||
// re.FindStringSubmatch("192.168.0.0/24")
|
|
||||||
// >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"]
|
|
||||||
// re.FindStringSubmatch("192.168.0.1")
|
|
||||||
// >>> ["192.168.0.1" "192.168.0.1" "" ""]
|
|
||||||
m := re.FindStringSubmatch(args[0])
|
|
||||||
if len(m) < 4 {
|
if len(m) < 4 {
|
||||||
return nil, invalidIPv4PrefixError
|
return nil, invalidIPv4PrefixError
|
||||||
}
|
}
|
||||||
@ -3328,14 +3374,7 @@ func flowSpecPrefixParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (F
|
|||||||
return nil, fmt.Errorf("invalid arguments for ipv6 prefix: %q", args)
|
return nil, fmt.Errorf("invalid arguments for ipv6 prefix: %q", args)
|
||||||
}
|
}
|
||||||
invalidIPv6PrefixError := fmt.Errorf("invalid ipv6 prefix: %s", args[0])
|
invalidIPv6PrefixError := fmt.Errorf("invalid ipv6 prefix: %s", args[0])
|
||||||
re := regexp.MustCompile("^([a-fA-F\\d:.]+)(/(\\d{1,3}))?(/(\\d{1,3}))?")
|
m := _regexpFindIPv6Prefix.FindStringSubmatch(args[0])
|
||||||
// re.FindStringSubmatch("2001:dB8::/64")
|
|
||||||
// >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""]
|
|
||||||
// re.FindStringSubmatch("2001:dB8::/64/8")
|
|
||||||
// >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"]
|
|
||||||
// re.FindStringSubmatch("2001:dB8::1")
|
|
||||||
// >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""]
|
|
||||||
m := re.FindStringSubmatch(args[0])
|
|
||||||
if len(m) < 4 {
|
if len(m) < 4 {
|
||||||
return nil, invalidIPv6PrefixError
|
return nil, invalidIPv6PrefixError
|
||||||
}
|
}
|
||||||
@ -3416,13 +3455,9 @@ func flowSpecTcpFlagParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (F
|
|||||||
|
|
||||||
argsLen := len(args)
|
argsLen := len(args)
|
||||||
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
||||||
// Note: "(-*)" and "(.*)" catch the invalid flags
|
|
||||||
re := regexp.MustCompile("(&?)(==|=|!|!=|=!)?(-*)([FSRPAUCE]+)(.*)")
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
// Example: In this case, "Z" is unsupported flag type.
|
m := _regexpFlowSpecTCPFlag.FindStringSubmatch(arg)
|
||||||
// re.FindStringSubmatch("&==-SZU")
|
|
||||||
// >>> ["&==-SZU" "&" "==" "-" "S" "ZU"]
|
|
||||||
m := re.FindStringSubmatch(arg)
|
|
||||||
if len(m) < 6 {
|
if len(m) < 6 {
|
||||||
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
||||||
} else if mLast := m[len(m)-1]; mLast != "" || m[3] != "" {
|
} else if mLast := m[len(m)-1]; mLast != "" || m[3] != "" {
|
||||||
@ -3472,13 +3507,9 @@ func flowSpecFragmentParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (
|
|||||||
|
|
||||||
argsLen := len(args)
|
argsLen := len(args)
|
||||||
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
items := make([]*FlowSpecComponentItem, 0, argsLen)
|
||||||
// Note: "(.*)" catches the invalid flags
|
|
||||||
re := regexp.MustCompile("(&?)(==|=|!|!=|=!)?(((\\+)?(dont|is|first|last|not-a)-fragment)+)(.*)")
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
// Example:
|
m := _regexpFlowSpecFragment.FindStringSubmatch(arg)
|
||||||
// re.FindStringSubmatch("&!=+first-fragment+last-fragment+invalid-fragment")
|
|
||||||
// >>> ["&!=+first-fragment+last-fragment+invalid-fragment" "&" "!=" "+first-fragment+last-fragment" "+last-fragment" "+" "last" "+invalid-fragment"]
|
|
||||||
m := re.FindStringSubmatch(arg)
|
|
||||||
if len(m) < 4 {
|
if len(m) < 4 {
|
||||||
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args)
|
||||||
} else if mLast := m[len(m)-1]; mLast != "" {
|
} else if mLast := m[len(m)-1]; mLast != "" {
|
||||||
@ -3921,13 +3952,10 @@ func (v *FlowSpecComponentItem) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *FlowSpecComponentItem) Serialize() ([]byte, error) {
|
func (v *FlowSpecComponentItem) Serialize() ([]byte, error) {
|
||||||
if v.Value < 0 {
|
if v.Op > math.MaxUint8 {
|
||||||
return nil, fmt.Errorf("invalid value size(too small): %d", v.Value)
|
|
||||||
}
|
|
||||||
if v.Op < 0 || v.Op > math.MaxUint8 {
|
|
||||||
return nil, fmt.Errorf("invalid op size: %d", v.Op)
|
return nil, fmt.Errorf("invalid op size: %d", v.Op)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
order := uint32(math.Log2(float64(v.Len())))
|
order := uint32(math.Log2(float64(v.Len())))
|
||||||
buf := make([]byte, 1+(1<<order))
|
buf := make([]byte, 1+(1<<order))
|
||||||
buf[0] = byte(uint32(v.Op) | order<<4)
|
buf[0] = byte(uint32(v.Op) | order<<4)
|
||||||
@ -4755,12 +4783,32 @@ func GetRouteFamily(name string) (RouteFamily, error) {
|
|||||||
return RouteFamily(0), fmt.Errorf("%s isn't a valid route family name", name)
|
return RouteFamily(0), fmt.Errorf("%s isn't a valid route family name", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPrefixFromRouteFamily(afi uint16, safi uint8) (prefix AddrPrefixInterface, err error) {
|
func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (prefix AddrPrefixInterface, err error) {
|
||||||
switch AfiSafiToRouteFamily(afi, safi) {
|
family := AfiSafiToRouteFamily(afi, safi)
|
||||||
|
|
||||||
|
f := func(s string) AddrPrefixInterface {
|
||||||
|
addr, net, _ := net.ParseCIDR(s)
|
||||||
|
len, _ := net.Mask.Size()
|
||||||
|
switch family {
|
||||||
|
case RF_IPv4_UC, RF_IPv4_MC:
|
||||||
|
return NewIPAddrPrefix(uint8(len), addr.String())
|
||||||
|
}
|
||||||
|
return NewIPv6AddrPrefix(uint8(len), addr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch family {
|
||||||
case RF_IPv4_UC, RF_IPv4_MC:
|
case RF_IPv4_UC, RF_IPv4_MC:
|
||||||
prefix = NewIPAddrPrefix(0, "")
|
if len(prefixStr) > 0 {
|
||||||
|
prefix = f(prefixStr[0])
|
||||||
|
} else {
|
||||||
|
prefix = NewIPAddrPrefix(0, "")
|
||||||
|
}
|
||||||
case RF_IPv6_UC, RF_IPv6_MC:
|
case RF_IPv6_UC, RF_IPv6_MC:
|
||||||
prefix = NewIPv6AddrPrefix(0, "")
|
if len(prefixStr) > 0 {
|
||||||
|
prefix = f(prefixStr[0])
|
||||||
|
} else {
|
||||||
|
prefix = NewIPv6AddrPrefix(0, "")
|
||||||
|
}
|
||||||
case RF_IPv4_VPN:
|
case RF_IPv4_VPN:
|
||||||
prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil)
|
prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil)
|
||||||
case RF_IPv6_VPN:
|
case RF_IPv6_VPN:
|
||||||
@ -5438,7 +5486,7 @@ func (p *PathAttributeAsPath) DecodeFromBytes(data []byte, options ...*Marshalli
|
|||||||
}
|
}
|
||||||
for len(value) > 0 {
|
for len(value) > 0 {
|
||||||
var tuple AsPathParamInterface
|
var tuple AsPathParamInterface
|
||||||
if isAs4 == true {
|
if isAs4 {
|
||||||
tuple = &As4PathParam{}
|
tuple = &As4PathParam{}
|
||||||
} else {
|
} else {
|
||||||
tuple = &AsPathParam{}
|
tuple = &AsPathParam{}
|
||||||
@ -5448,9 +5496,6 @@ func (p *PathAttributeAsPath) DecodeFromBytes(data []byte, options ...*Marshalli
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.Value = append(p.Value, tuple)
|
p.Value = append(p.Value, tuple)
|
||||||
if tuple.Len() > len(value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
value = value[tuple.Len():]
|
value = value[tuple.Len():]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -5827,19 +5872,19 @@ type WellKnownCommunity uint32
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
COMMUNITY_INTERNET WellKnownCommunity = 0x00000000
|
COMMUNITY_INTERNET WellKnownCommunity = 0x00000000
|
||||||
COMMUNITY_PLANNED_SHUT = 0xffff0000
|
COMMUNITY_PLANNED_SHUT WellKnownCommunity = 0xffff0000
|
||||||
COMMUNITY_ACCEPT_OWN = 0xffff0001
|
COMMUNITY_ACCEPT_OWN WellKnownCommunity = 0xffff0001
|
||||||
COMMUNITY_ROUTE_FILTER_TRANSLATED_v4 = 0xffff0002
|
COMMUNITY_ROUTE_FILTER_TRANSLATED_v4 WellKnownCommunity = 0xffff0002
|
||||||
COMMUNITY_ROUTE_FILTER_v4 = 0xffff0003
|
COMMUNITY_ROUTE_FILTER_v4 WellKnownCommunity = 0xffff0003
|
||||||
COMMUNITY_ROUTE_FILTER_TRANSLATED_v6 = 0xffff0004
|
COMMUNITY_ROUTE_FILTER_TRANSLATED_v6 WellKnownCommunity = 0xffff0004
|
||||||
COMMUNITY_ROUTE_FILTER_v6 = 0xffff0005
|
COMMUNITY_ROUTE_FILTER_v6 WellKnownCommunity = 0xffff0005
|
||||||
COMMUNITY_LLGR_STALE = 0xffff0006
|
COMMUNITY_LLGR_STALE WellKnownCommunity = 0xffff0006
|
||||||
COMMUNITY_NO_LLGR = 0xffff0007
|
COMMUNITY_NO_LLGR WellKnownCommunity = 0xffff0007
|
||||||
COMMUNITY_BLACKHOLE = 0xffff029a
|
COMMUNITY_BLACKHOLE WellKnownCommunity = 0xffff029a
|
||||||
COMMUNITY_NO_EXPORT = 0xffffff01
|
COMMUNITY_NO_EXPORT WellKnownCommunity = 0xffffff01
|
||||||
COMMUNITY_NO_ADVERTISE = 0xffffff02
|
COMMUNITY_NO_ADVERTISE WellKnownCommunity = 0xffffff02
|
||||||
COMMUNITY_NO_EXPORT_SUBCONFED = 0xffffff03
|
COMMUNITY_NO_EXPORT_SUBCONFED WellKnownCommunity = 0xffffff03
|
||||||
COMMUNITY_NO_PEER = 0xffffff04
|
COMMUNITY_NO_PEER WellKnownCommunity = 0xffffff04
|
||||||
)
|
)
|
||||||
|
|
||||||
var WellKnownCommunityNameMap = map[WellKnownCommunity]string{
|
var WellKnownCommunityNameMap = map[WellKnownCommunity]string{
|
||||||
@ -5946,7 +5991,7 @@ func (p *PathAttributeOriginatorId) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathAttributeOriginatorId) Serialize(options ...*MarshallingOption) ([]byte, error) {
|
func (p *PathAttributeOriginatorId) Serialize(options ...*MarshallingOption) ([]byte, error) {
|
||||||
buf := make([]byte, 4, 4)
|
buf := make([]byte, 4)
|
||||||
copy(buf, p.Value)
|
copy(buf, p.Value)
|
||||||
return p.PathAttribute.Serialize(buf, options...)
|
return p.PathAttribute.Serialize(buf, options...)
|
||||||
}
|
}
|
||||||
@ -6622,6 +6667,19 @@ func ParseRouteTarget(rt string) (ExtendedCommunityInterface, error) {
|
|||||||
return ParseExtendedCommunity(EC_SUBTYPE_ROUTE_TARGET, rt)
|
return ParseExtendedCommunity(EC_SUBTYPE_ROUTE_TARGET, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SerializeExtendedCommunities(comms []ExtendedCommunityInterface) ([][]byte, error) {
|
||||||
|
var bufs [][]byte
|
||||||
|
var err error
|
||||||
|
for _, c := range comms {
|
||||||
|
buf, err := c.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bufs = append(bufs, buf)
|
||||||
|
}
|
||||||
|
return bufs, err
|
||||||
|
}
|
||||||
|
|
||||||
type ValidationState uint8
|
type ValidationState uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -6647,7 +6705,7 @@ type ValidationExtended struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *ValidationExtended) Serialize() ([]byte, error) {
|
func (e *ValidationExtended) Serialize() ([]byte, error) {
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
typ, subType := e.GetTypes()
|
typ, subType := e.GetTypes()
|
||||||
buf[0] = byte(typ)
|
buf[0] = byte(typ)
|
||||||
buf[1] = byte(subType)
|
buf[1] = byte(subType)
|
||||||
@ -6687,7 +6745,7 @@ type ColorExtended struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *ColorExtended) Serialize() ([]byte, error) {
|
func (e *ColorExtended) Serialize() ([]byte, error) {
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
typ, subType := e.GetTypes()
|
typ, subType := e.GetTypes()
|
||||||
buf[0] = byte(typ)
|
buf[0] = byte(typ)
|
||||||
buf[1] = byte(subType)
|
buf[1] = byte(subType)
|
||||||
@ -6727,7 +6785,7 @@ type EncapExtended struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EncapExtended) Serialize() ([]byte, error) {
|
func (e *EncapExtended) Serialize() ([]byte, error) {
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
typ, subType := e.GetTypes()
|
typ, subType := e.GetTypes()
|
||||||
buf[0] = byte(typ)
|
buf[0] = byte(typ)
|
||||||
buf[1] = byte(subType)
|
buf[1] = byte(subType)
|
||||||
@ -6787,7 +6845,7 @@ type DefaultGatewayExtended struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *DefaultGatewayExtended) Serialize() ([]byte, error) {
|
func (e *DefaultGatewayExtended) Serialize() ([]byte, error) {
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
typ, subType := e.GetTypes()
|
typ, subType := e.GetTypes()
|
||||||
buf[0] = byte(typ)
|
buf[0] = byte(typ)
|
||||||
buf[1] = byte(subType)
|
buf[1] = byte(subType)
|
||||||
@ -6826,7 +6884,7 @@ func (e *OpaqueExtended) Serialize() ([]byte, error) {
|
|||||||
if len(e.Value) != 7 {
|
if len(e.Value) != 7 {
|
||||||
return nil, fmt.Errorf("invalid value length for opaque extended community: %d", len(e.Value))
|
return nil, fmt.Errorf("invalid value length for opaque extended community: %d", len(e.Value))
|
||||||
}
|
}
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
if e.IsTransitive {
|
if e.IsTransitive {
|
||||||
buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE)
|
buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE)
|
||||||
} else {
|
} else {
|
||||||
@ -6837,7 +6895,7 @@ func (e *OpaqueExtended) Serialize() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *OpaqueExtended) String() string {
|
func (e *OpaqueExtended) String() string {
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
copy(buf[1:], e.Value)
|
copy(buf[1:], e.Value)
|
||||||
return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf))
|
return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf))
|
||||||
}
|
}
|
||||||
@ -6868,7 +6926,7 @@ func (e *OpaqueExtended) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewOpaqueExtended(isTransitive bool, value []byte) *OpaqueExtended {
|
func NewOpaqueExtended(isTransitive bool, value []byte) *OpaqueExtended {
|
||||||
v := make([]byte, 7, 7)
|
v := make([]byte, 7)
|
||||||
copy(v, value)
|
copy(v, value)
|
||||||
return &OpaqueExtended{
|
return &OpaqueExtended{
|
||||||
IsTransitive: isTransitive,
|
IsTransitive: isTransitive,
|
||||||
@ -7489,7 +7547,7 @@ func (e *UnknownExtended) Serialize() ([]byte, error) {
|
|||||||
if len(e.Value) != 7 {
|
if len(e.Value) != 7 {
|
||||||
return nil, fmt.Errorf("invalid value length for unknown extended community: %d", len(e.Value))
|
return nil, fmt.Errorf("invalid value length for unknown extended community: %d", len(e.Value))
|
||||||
}
|
}
|
||||||
buf := make([]byte, 8, 8)
|
buf := make([]byte, 8)
|
||||||
buf[0] = uint8(e.Type)
|
buf[0] = uint8(e.Type)
|
||||||
copy(buf[1:], e.Value)
|
copy(buf[1:], e.Value)
|
||||||
return buf, nil
|
return buf, nil
|
||||||
@ -7524,7 +7582,7 @@ func (e *UnknownExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommuni
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewUnknownExtended(typ ExtendedCommunityAttrType, value []byte) *UnknownExtended {
|
func NewUnknownExtended(typ ExtendedCommunityAttrType, value []byte) *UnknownExtended {
|
||||||
v := make([]byte, 7, 7)
|
v := make([]byte, 7)
|
||||||
copy(v, value)
|
copy(v, value)
|
||||||
return &UnknownExtended{
|
return &UnknownExtended{
|
||||||
Type: typ,
|
Type: typ,
|
||||||
@ -7668,9 +7726,11 @@ func (p *PathAttributeAs4Path) DecodeFromBytes(data []byte, options ...*Marshall
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if isAs4 == false {
|
|
||||||
|
if !isAs4 {
|
||||||
return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed")
|
return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed")
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(value) > 0 {
|
for len(value) > 0 {
|
||||||
tuple := &As4PathParam{}
|
tuple := &As4PathParam{}
|
||||||
tuple.DecodeFromBytes(value)
|
tuple.DecodeFromBytes(value)
|
||||||
@ -8086,7 +8146,7 @@ func (p *TunnelEncapTLV) Serialize() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *TunnelEncapTLV) String() string {
|
func (p *TunnelEncapTLV) String() string {
|
||||||
tlvList := make([]string, len(p.Value), len(p.Value))
|
tlvList := make([]string, len(p.Value))
|
||||||
for i, v := range p.Value {
|
for i, v := range p.Value {
|
||||||
tlvList[i] = v.String()
|
tlvList[i] = v.String()
|
||||||
}
|
}
|
||||||
@ -8145,7 +8205,7 @@ func (p *PathAttributeTunnelEncap) Serialize(options ...*MarshallingOption) ([]b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathAttributeTunnelEncap) String() string {
|
func (p *PathAttributeTunnelEncap) String() string {
|
||||||
tlvList := make([]string, len(p.Value), len(p.Value))
|
tlvList := make([]string, len(p.Value))
|
||||||
for i, v := range p.Value {
|
for i, v := range p.Value {
|
||||||
tlvList[i] = v.String()
|
tlvList[i] = v.String()
|
||||||
}
|
}
|
||||||
@ -9198,10 +9258,12 @@ func (msg *BGPHeader) DecodeFromBytes(data []byte, options ...*MarshallingOption
|
|||||||
if uint16(len(data)) < BGP_HEADER_LENGTH {
|
if uint16(len(data)) < BGP_HEADER_LENGTH {
|
||||||
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "not all BGP message header")
|
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "not all BGP message header")
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Len = binary.BigEndian.Uint16(data[16:18])
|
msg.Len = binary.BigEndian.Uint16(data[16:18])
|
||||||
if int(msg.Len) < BGP_HEADER_LENGTH {
|
if int(msg.Len) < BGP_HEADER_LENGTH {
|
||||||
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "unknown message type")
|
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "unknown message type")
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Type = data[18]
|
msg.Type = data[18]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -9251,6 +9313,11 @@ func ParseBGPMessage(data []byte, options ...*MarshallingOption) (*BGPMessage, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if int(h.Len) > len(data) {
|
||||||
|
return nil, NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "unknown message type")
|
||||||
|
}
|
||||||
|
|
||||||
return parseBody(h, data[19:h.Len], options...)
|
return parseBody(h, data[19:h.Len], options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/osrg/gobgp/packet/bgp/validate.go
generated
vendored
2
vendor/github.com/osrg/gobgp/packet/bgp/validate.go
generated
vendored
@ -274,7 +274,7 @@ func validateAsPathValueBytes(data []byte) (bool, error) {
|
|||||||
return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect")
|
return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect")
|
||||||
}
|
}
|
||||||
segLength := int(asNum)
|
segLength := int(asNum)
|
||||||
if use4byte == true {
|
if use4byte {
|
||||||
segLength *= 4
|
segLength *= 4
|
||||||
} else {
|
} else {
|
||||||
segLength *= 2
|
segLength *= 2
|
||||||
|
|||||||
3
vendor/github.com/osrg/gobgp/packet/bmp/bmp.go
generated
vendored
3
vendor/github.com/osrg/gobgp/packet/bmp/bmp.go
generated
vendored
@ -391,8 +391,9 @@ func NewBMPPeerDownNotification(p BMPPeerHeader, reason uint8, notification *bgp
|
|||||||
switch reason {
|
switch reason {
|
||||||
case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
|
case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
|
||||||
b.BGPNotification = notification
|
b.BGPNotification = notification
|
||||||
default:
|
case BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION:
|
||||||
b.Data = data
|
b.Data = data
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
return &BMPMessage{
|
return &BMPMessage{
|
||||||
Header: BMPHeader{
|
Header: BMPHeader{
|
||||||
|
|||||||
50
vendor/github.com/osrg/gobgp/server/bmp.go
generated
vendored
50
vendor/github.com/osrg/gobgp/server/bmp.go
generated
vendored
@ -17,14 +17,15 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
"github.com/osrg/gobgp/packet/bmp"
|
"github.com/osrg/gobgp/packet/bmp"
|
||||||
"github.com/osrg/gobgp/table"
|
"github.com/osrg/gobgp/table"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ribout map[string][]*table.Path
|
type ribout map[string][]*table.Path
|
||||||
@ -166,16 +167,22 @@ func (b *bmpClient) loop() {
|
|||||||
ID: msg.PeerID,
|
ID: msg.PeerID,
|
||||||
}
|
}
|
||||||
if msg.Payload == nil {
|
if msg.Payload == nil {
|
||||||
pathList := make([]*table.Path, 0, len(msg.PathList))
|
var pathList []*table.Path
|
||||||
for _, p := range msg.PathList {
|
if msg.Init {
|
||||||
if b.ribout.update(p) {
|
pathList = msg.PathList
|
||||||
pathList = append(pathList, p)
|
} else {
|
||||||
|
for _, p := range msg.PathList {
|
||||||
|
if b.ribout.update(p) {
|
||||||
|
pathList = append(pathList, p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, u := range table.CreateUpdateMsgFromPaths(pathList) {
|
for _, path := range pathList {
|
||||||
payload, _ := u.Serialize()
|
for _, u := range table.CreateUpdateMsgFromPaths([]*table.Path{path}) {
|
||||||
if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, true, info, msg.Timestamp.Unix(), payload)); err != nil {
|
payload, _ := u.Serialize()
|
||||||
return false
|
if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, true, info, msg.Timestamp.Unix(), payload)); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -198,17 +205,12 @@ func (b *bmpClient) loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *WatchEventPeerState:
|
case *WatchEventPeerState:
|
||||||
info := &table.PeerInfo{
|
|
||||||
Address: msg.PeerAddress,
|
|
||||||
AS: msg.PeerAS,
|
|
||||||
ID: msg.PeerID,
|
|
||||||
}
|
|
||||||
if msg.State == bgp.BGP_FSM_ESTABLISHED {
|
if msg.State == bgp.BGP_FSM_ESTABLISHED {
|
||||||
if err := write(bmpPeerUp(msg.LocalAddress.String(), msg.LocalPort, msg.PeerPort, msg.SentOpen, msg.RecvOpen, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.Timestamp.Unix())); err != nil {
|
if err := write(bmpPeerUp(msg, bmp.BMP_PEER_TYPE_GLOBAL, false, 0)); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := write(bmpPeerDown(bmp.BMP_PEER_DOWN_REASON_UNKNOWN, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.Timestamp.Unix())); err != nil {
|
if err := write(bmpPeerDown(msg, bmp.BMP_PEER_TYPE_GLOBAL, false, 0)); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,22 +259,22 @@ type bmpClient struct {
|
|||||||
ribout ribout
|
ribout ribout
|
||||||
}
|
}
|
||||||
|
|
||||||
func bmpPeerUp(laddr string, lport, rport uint16, sent, recv *bgp.BGPMessage, t uint8, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64) *bmp.BMPMessage {
|
func bmpPeerUp(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
|
||||||
var flags uint8 = 0
|
var flags uint8 = 0
|
||||||
if policy {
|
if policy {
|
||||||
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
|
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
|
||||||
}
|
}
|
||||||
ph := bmp.NewBMPPeerHeader(t, flags, pd, peeri.Address.String(), peeri.AS, peeri.ID.String(), float64(timestamp))
|
ph := bmp.NewBMPPeerHeader(t, flags, pd, ev.PeerAddress.String(), ev.PeerAS, ev.PeerID.String(), float64(ev.Timestamp.Unix()))
|
||||||
return bmp.NewBMPPeerUpNotification(*ph, laddr, lport, rport, sent, recv)
|
return bmp.NewBMPPeerUpNotification(*ph, ev.LocalAddress.String(), ev.LocalPort, ev.PeerPort, ev.SentOpen, ev.RecvOpen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bmpPeerDown(reason uint8, t uint8, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64) *bmp.BMPMessage {
|
func bmpPeerDown(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
|
||||||
var flags uint8 = 0
|
var flags uint8 = 0
|
||||||
if policy {
|
if policy {
|
||||||
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
|
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
|
||||||
}
|
}
|
||||||
ph := bmp.NewBMPPeerHeader(t, flags, pd, peeri.Address.String(), peeri.AS, peeri.ID.String(), float64(timestamp))
|
ph := bmp.NewBMPPeerHeader(t, flags, pd, ev.PeerAddress.String(), ev.PeerAS, ev.PeerID.String(), float64(ev.Timestamp.Unix()))
|
||||||
return bmp.NewBMPPeerDownNotification(*ph, reason, nil, []byte{})
|
return bmp.NewBMPPeerDownNotification(*ph, uint8(ev.StateReason.PeerDownReason), ev.StateReason.BGPNotification, ev.StateReason.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bmpPeerRoute(t uint8, policy bool, pd uint64, fourBytesAs bool, peeri *table.PeerInfo, timestamp int64, payload []byte) *bmp.BMPMessage {
|
func bmpPeerRoute(t uint8, policy bool, pd uint64, fourBytesAs bool, peeri *table.PeerInfo, timestamp int64, payload []byte) *bmp.BMPMessage {
|
||||||
|
|||||||
312
vendor/github.com/osrg/gobgp/server/fsm.go
generated
vendored
312
vendor/github.com/osrg/gobgp/server/fsm.go
generated
vendored
@ -21,39 +21,115 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eapache/channels"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"gopkg.in/tomb.v2"
|
|
||||||
|
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
"github.com/osrg/gobgp/packet/bmp"
|
"github.com/osrg/gobgp/packet/bmp"
|
||||||
"github.com/osrg/gobgp/table"
|
"github.com/osrg/gobgp/table"
|
||||||
|
|
||||||
|
"github.com/eapache/channels"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/tomb.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FsmStateReason string
|
type PeerDownReason int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FSM_DYING = "dying"
|
PEER_DOWN_REASON_UNKNOWN PeerDownReason = iota
|
||||||
FSM_ADMIN_DOWN = "admin-down"
|
PEER_DOWN_BY_LOCAL
|
||||||
FSM_READ_FAILED = "read-failed"
|
PEER_DOWN_BY_LOCAL_WITHOUT_NOTIFICATION
|
||||||
FSM_WRITE_FAILED = "write-failed"
|
PEER_DOWN_BY_REMOTE
|
||||||
FSM_NOTIFICATION_SENT = "notification-sent"
|
PEER_DOWN_BY_REMOTE_WITHOUT_NOTIFICATION
|
||||||
FSM_NOTIFICATION_RECV = "notification-received"
|
PEER_DOWN_BY_BMP_CONFIGURATION
|
||||||
FSM_HOLD_TIMER_EXPIRED = "hold-timer-expired"
|
|
||||||
FSM_IDLE_HOLD_TIMER_EXPIRED = "idle-hold-timer-expired"
|
|
||||||
FSM_RESTART_TIMER_EXPIRED = "restart-timer-expired"
|
|
||||||
FSM_GRACEFUL_RESTART = "graceful-restart"
|
|
||||||
FSM_INVALID_MSG = "invalid-msg"
|
|
||||||
FSM_NEW_CONNECTION = "new-connection"
|
|
||||||
FSM_OPEN_MSG_RECEIVED = "open-msg-received"
|
|
||||||
FSM_OPEN_MSG_NEGOTIATED = "open-msg-negotiated"
|
|
||||||
FSM_HARD_RESET = "hard-reset"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FsmStateReasonType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
FSM_DYING FsmStateReasonType = iota
|
||||||
|
FSM_ADMIN_DOWN
|
||||||
|
FSM_READ_FAILED
|
||||||
|
FSM_WRITE_FAILED
|
||||||
|
FSM_NOTIFICATION_SENT
|
||||||
|
FSM_NOTIFICATION_RECV
|
||||||
|
FSM_HOLD_TIMER_EXPIRED
|
||||||
|
FSM_IDLE_HOLD_TIMER_EXPIRED
|
||||||
|
FSM_RESTART_TIMER_EXPIRED
|
||||||
|
FSM_GRACEFUL_RESTART
|
||||||
|
FSM_INVALID_MSG
|
||||||
|
FSM_NEW_CONNECTION
|
||||||
|
FSM_OPEN_MSG_RECEIVED
|
||||||
|
FSM_OPEN_MSG_NEGOTIATED
|
||||||
|
FSM_HARD_RESET
|
||||||
|
)
|
||||||
|
|
||||||
|
type FsmStateReason struct {
|
||||||
|
Type FsmStateReasonType
|
||||||
|
PeerDownReason PeerDownReason
|
||||||
|
BGPNotification *bgp.BGPMessage
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFsmStateReason(typ FsmStateReasonType, notif *bgp.BGPMessage, data []byte) *FsmStateReason {
|
||||||
|
var reasonCode PeerDownReason
|
||||||
|
switch typ {
|
||||||
|
case FSM_DYING, FSM_INVALID_MSG, FSM_NOTIFICATION_SENT, FSM_HOLD_TIMER_EXPIRED, FSM_IDLE_HOLD_TIMER_EXPIRED, FSM_RESTART_TIMER_EXPIRED:
|
||||||
|
reasonCode = PEER_DOWN_BY_LOCAL
|
||||||
|
case FSM_ADMIN_DOWN:
|
||||||
|
reasonCode = PEER_DOWN_BY_LOCAL_WITHOUT_NOTIFICATION
|
||||||
|
case FSM_NOTIFICATION_RECV, FSM_GRACEFUL_RESTART, FSM_HARD_RESET:
|
||||||
|
reasonCode = PEER_DOWN_BY_REMOTE
|
||||||
|
case FSM_READ_FAILED, FSM_WRITE_FAILED:
|
||||||
|
reasonCode = PEER_DOWN_BY_REMOTE_WITHOUT_NOTIFICATION
|
||||||
|
}
|
||||||
|
return &FsmStateReason{
|
||||||
|
Type: typ,
|
||||||
|
PeerDownReason: reasonCode,
|
||||||
|
BGPNotification: notif,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r FsmStateReason) String() string {
|
||||||
|
switch r.Type {
|
||||||
|
case FSM_DYING:
|
||||||
|
return "dying"
|
||||||
|
case FSM_ADMIN_DOWN:
|
||||||
|
return "admin-down"
|
||||||
|
case FSM_READ_FAILED:
|
||||||
|
return "read-failed"
|
||||||
|
case FSM_WRITE_FAILED:
|
||||||
|
return "write-failed"
|
||||||
|
case FSM_NOTIFICATION_SENT:
|
||||||
|
body := r.BGPNotification.Body.(*bgp.BGPNotification)
|
||||||
|
return fmt.Sprintf("notification-sent %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())
|
||||||
|
case FSM_NOTIFICATION_RECV:
|
||||||
|
body := r.BGPNotification.Body.(*bgp.BGPNotification)
|
||||||
|
return fmt.Sprintf("notification-received %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())
|
||||||
|
case FSM_HOLD_TIMER_EXPIRED:
|
||||||
|
return "hold-timer-expired"
|
||||||
|
case FSM_IDLE_HOLD_TIMER_EXPIRED:
|
||||||
|
return "idle-hold-timer-expired"
|
||||||
|
case FSM_RESTART_TIMER_EXPIRED:
|
||||||
|
return "restart-timer-expired"
|
||||||
|
case FSM_GRACEFUL_RESTART:
|
||||||
|
return "graceful-restart"
|
||||||
|
case FSM_INVALID_MSG:
|
||||||
|
return "invalid-msg"
|
||||||
|
case FSM_NEW_CONNECTION:
|
||||||
|
return "new-connection"
|
||||||
|
case FSM_OPEN_MSG_RECEIVED:
|
||||||
|
return "open-msg-received"
|
||||||
|
case FSM_OPEN_MSG_NEGOTIATED:
|
||||||
|
return "open-msg-negotiated"
|
||||||
|
case FSM_HARD_RESET:
|
||||||
|
return "hard-reset"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type FsmMsgType int
|
type FsmMsgType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -64,13 +140,14 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FsmMsg struct {
|
type FsmMsg struct {
|
||||||
MsgType FsmMsgType
|
MsgType FsmMsgType
|
||||||
MsgSrc string
|
MsgSrc string
|
||||||
MsgData interface{}
|
MsgData interface{}
|
||||||
PathList []*table.Path
|
StateReason *FsmStateReason
|
||||||
timestamp time.Time
|
PathList []*table.Path
|
||||||
payload []byte
|
timestamp time.Time
|
||||||
Version uint
|
payload []byte
|
||||||
|
Version uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type FsmOutgoingMsg struct {
|
type FsmOutgoingMsg struct {
|
||||||
@ -117,7 +194,7 @@ type FSM struct {
|
|||||||
gConf *config.Global
|
gConf *config.Global
|
||||||
pConf *config.Neighbor
|
pConf *config.Neighbor
|
||||||
state bgp.FSMState
|
state bgp.FSMState
|
||||||
reason FsmStateReason
|
reason *FsmStateReason
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
connCh chan net.Conn
|
connCh chan net.Conn
|
||||||
idleHoldTime float64
|
idleHoldTime float64
|
||||||
@ -289,14 +366,14 @@ func (fsm *FSM) LocalHostPort() (string, uint16) {
|
|||||||
return hostport(fsm.conn.LocalAddr())
|
return hostport(fsm.conn.LocalAddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fsm *FSM) sendNotificationFromErrorMsg(e *bgp.MessageError) error {
|
func (fsm *FSM) sendNotificationFromErrorMsg(e *bgp.MessageError) (*bgp.BGPMessage, error) {
|
||||||
if fsm.h != nil && fsm.h.conn != nil {
|
if fsm.h != nil && fsm.h.conn != nil {
|
||||||
m := bgp.NewBGPNotificationMessage(e.TypeCode, e.SubTypeCode, e.Data)
|
m := bgp.NewBGPNotificationMessage(e.TypeCode, e.SubTypeCode, e.Data)
|
||||||
b, _ := m.Serialize()
|
b, _ := m.Serialize()
|
||||||
_, err := fsm.h.conn.Write(b)
|
_, err := fsm.h.conn.Write(b)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fsm.bgpMessageStateUpdate(m.Header.Type, false)
|
fsm.bgpMessageStateUpdate(m.Header.Type, false)
|
||||||
fsm.h.sentNotification = bgp.NewNotificationErrorCode(e.TypeCode, e.SubTypeCode).String()
|
fsm.h.sentNotification = m
|
||||||
}
|
}
|
||||||
fsm.h.conn.Close()
|
fsm.h.conn.Close()
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -304,12 +381,12 @@ func (fsm *FSM) sendNotificationFromErrorMsg(e *bgp.MessageError) error {
|
|||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"Data": e,
|
"Data": e,
|
||||||
}).Warn("sent notification")
|
}).Warn("sent notification")
|
||||||
return nil
|
return m, nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.State.NeighborAddress)
|
return nil, fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.State.NeighborAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fsm *FSM) sendNotification(code, subType uint8, data []byte, msg string) error {
|
func (fsm *FSM) sendNotification(code, subType uint8, data []byte, msg string) (*bgp.BGPMessage, error) {
|
||||||
e := bgp.NewMessageError(code, subType, data, msg)
|
e := bgp.NewMessageError(code, subType, data, msg)
|
||||||
return fsm.sendNotificationFromErrorMsg(e.(*bgp.MessageError))
|
return fsm.sendNotificationFromErrorMsg(e.(*bgp.MessageError))
|
||||||
}
|
}
|
||||||
@ -403,18 +480,18 @@ type FSMHandler struct {
|
|||||||
fsm *FSM
|
fsm *FSM
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
msgCh *channels.InfiniteChannel
|
msgCh *channels.InfiniteChannel
|
||||||
errorCh chan FsmStateReason
|
stateReasonCh chan FsmStateReason
|
||||||
incoming *channels.InfiniteChannel
|
incoming *channels.InfiniteChannel
|
||||||
stateCh chan *FsmMsg
|
stateCh chan *FsmMsg
|
||||||
outgoing *channels.InfiniteChannel
|
outgoing *channels.InfiniteChannel
|
||||||
holdTimerResetCh chan bool
|
holdTimerResetCh chan bool
|
||||||
sentNotification string
|
sentNotification *bgp.BGPMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFSMHandler(fsm *FSM, incoming *channels.InfiniteChannel, stateCh chan *FsmMsg, outgoing *channels.InfiniteChannel) *FSMHandler {
|
func NewFSMHandler(fsm *FSM, incoming *channels.InfiniteChannel, stateCh chan *FsmMsg, outgoing *channels.InfiniteChannel) *FSMHandler {
|
||||||
h := &FSMHandler{
|
h := &FSMHandler{
|
||||||
fsm: fsm,
|
fsm: fsm,
|
||||||
errorCh: make(chan FsmStateReason, 2),
|
stateReasonCh: make(chan FsmStateReason, 2),
|
||||||
incoming: incoming,
|
incoming: incoming,
|
||||||
stateCh: stateCh,
|
stateCh: stateCh,
|
||||||
outgoing: outgoing,
|
outgoing: outgoing,
|
||||||
@ -424,14 +501,14 @@ func NewFSMHandler(fsm *FSM, incoming *channels.InfiniteChannel, stateCh chan *F
|
|||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) {
|
func (h *FSMHandler) idle() (bgp.FSMState, *FsmStateReason) {
|
||||||
fsm := h.fsm
|
fsm := h.fsm
|
||||||
|
|
||||||
idleHoldTimer := time.NewTimer(time.Second * time.Duration(fsm.idleHoldTime))
|
idleHoldTimer := time.NewTimer(time.Second * time.Duration(fsm.idleHoldTime))
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-h.t.Dying():
|
case <-h.t.Dying():
|
||||||
return -1, FSM_DYING
|
return -1, NewFsmStateReason(FSM_DYING, nil, nil)
|
||||||
case <-fsm.gracefulRestartTimer.C:
|
case <-fsm.gracefulRestartTimer.C:
|
||||||
if fsm.pConf.GracefulRestart.State.PeerRestarting {
|
if fsm.pConf.GracefulRestart.State.PeerRestarting {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -439,7 +516,7 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Warn("graceful restart timer expired")
|
}).Warn("graceful restart timer expired")
|
||||||
return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_RESTART_TIMER_EXPIRED, nil, nil)
|
||||||
}
|
}
|
||||||
case conn, ok := <-fsm.connCh:
|
case conn, ok := <-fsm.connCh:
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -460,7 +537,7 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Duration": fsm.idleHoldTime,
|
"Duration": fsm.idleHoldTime,
|
||||||
}).Debug("IdleHoldTimer expired")
|
}).Debug("IdleHoldTimer expired")
|
||||||
fsm.idleHoldTime = HOLDTIME_IDLE
|
fsm.idleHoldTime = HOLDTIME_IDLE
|
||||||
return bgp.BGP_FSM_ACTIVE, FSM_IDLE_HOLD_TIMER_EXPIRED
|
return bgp.BGP_FSM_ACTIVE, NewFsmStateReason(FSM_IDLE_HOLD_TIMER_EXPIRED, nil, nil)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.WithFields(log.Fields{"Topic": "Peer"}).Debug("IdleHoldTimer expired, but stay at idle because the admin state is DOWN")
|
log.WithFields(log.Fields{"Topic": "Peer"}).Debug("IdleHoldTimer expired, but stay at idle because the admin state is DOWN")
|
||||||
@ -483,12 +560,12 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) {
|
func (h *FSMHandler) active() (bgp.FSMState, *FsmStateReason) {
|
||||||
fsm := h.fsm
|
fsm := h.fsm
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-h.t.Dying():
|
case <-h.t.Dying():
|
||||||
return -1, FSM_DYING
|
return -1, NewFsmStateReason(FSM_DYING, nil, nil)
|
||||||
case conn, ok := <-fsm.connCh:
|
case conn, ok := <-fsm.connCh:
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
@ -530,7 +607,7 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) {
|
|||||||
}
|
}
|
||||||
// we don't implement delayed open timer so move to opensent right
|
// we don't implement delayed open timer so move to opensent right
|
||||||
// away.
|
// away.
|
||||||
return bgp.BGP_FSM_OPENSENT, FSM_NEW_CONNECTION
|
return bgp.BGP_FSM_OPENSENT, NewFsmStateReason(FSM_NEW_CONNECTION, nil, nil)
|
||||||
case <-fsm.gracefulRestartTimer.C:
|
case <-fsm.gracefulRestartTimer.C:
|
||||||
if fsm.pConf.GracefulRestart.State.PeerRestarting {
|
if fsm.pConf.GracefulRestart.State.PeerRestarting {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -538,16 +615,16 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Warn("graceful restart timer expired")
|
}).Warn("graceful restart timer expired")
|
||||||
return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_RESTART_TIMER_EXPIRED, nil, nil)
|
||||||
}
|
}
|
||||||
case err := <-h.errorCh:
|
case err := <-h.stateReasonCh:
|
||||||
return bgp.BGP_FSM_IDLE, err
|
return bgp.BGP_FSM_IDLE, &err
|
||||||
case stateOp := <-fsm.adminStateCh:
|
case stateOp := <-fsm.adminStateCh:
|
||||||
err := h.changeAdminState(stateOp.State)
|
err := h.changeAdminState(stateOp.State)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch stateOp.State {
|
switch stateOp.State {
|
||||||
case ADMIN_STATE_DOWN:
|
case ADMIN_STATE_DOWN:
|
||||||
return bgp.BGP_FSM_IDLE, FSM_ADMIN_DOWN
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_ADMIN_DOWN, nil, nil)
|
||||||
case ADMIN_STATE_UP:
|
case ADMIN_STATE_UP:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -779,17 +856,17 @@ func (h *FSMHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
|
func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
|
||||||
sendToErrorCh := func(reason FsmStateReason) {
|
sendToStateReasonCh := func(typ FsmStateReasonType, notif *bgp.BGPMessage) {
|
||||||
// probably doesn't happen but be cautious
|
// probably doesn't happen but be cautious
|
||||||
select {
|
select {
|
||||||
case h.errorCh <- reason:
|
case h.stateReasonCh <- *NewFsmStateReason(typ, notif, nil):
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headerBuf, err := readAll(h.conn, bgp.BGP_HEADER_LENGTH)
|
headerBuf, err := readAll(h.conn, bgp.BGP_HEADER_LENGTH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendToErrorCh(FSM_READ_FAILED)
|
sendToStateReasonCh(FSM_READ_FAILED, nil)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,7 +891,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
|
|||||||
|
|
||||||
bodyBuf, err := readAll(h.conn, int(hd.Len)-bgp.BGP_HEADER_LENGTH)
|
bodyBuf, err := readAll(h.conn, int(hd.Len)-bgp.BGP_HEADER_LENGTH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendToErrorCh(FSM_READ_FAILED)
|
sendToStateReasonCh(FSM_READ_FAILED, nil)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,25 +974,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
|
|||||||
return fmsg, err
|
return fmsg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC4271 9.1.2 Phase 2: Route Selection
|
|
||||||
//
|
|
||||||
// If the AS_PATH attribute of a BGP route contains an AS loop, the BGP
|
|
||||||
// route should be excluded from the Phase 2 decision function.
|
|
||||||
var asLoop bool
|
|
||||||
if attr := getPathAttrFromBGPUpdate(body, bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
|
|
||||||
asLoop = hasOwnASLoop(h.fsm.peerInfo.LocalAS, int(h.fsm.pConf.AsPathOptions.Config.AllowOwnAs), attr.(*bgp.PathAttributeAsPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmsg.PathList = table.ProcessMessage(m, h.fsm.peerInfo, fmsg.timestamp)
|
fmsg.PathList = table.ProcessMessage(m, h.fsm.peerInfo, fmsg.timestamp)
|
||||||
id := h.fsm.pConf.State.NeighborAddress
|
|
||||||
for _, path := range fmsg.PathList {
|
|
||||||
if path.IsEOR() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if asLoop || (h.fsm.policy.ApplyPolicy(id, table.POLICY_DIRECTION_IN, path, nil) == nil) {
|
|
||||||
path.Filter(id, table.POLICY_DIRECTION_IN)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case bgp.BGP_MSG_KEEPALIVE:
|
case bgp.BGP_MSG_KEEPALIVE:
|
||||||
// if the length of h.holdTimerResetCh
|
// if the length of h.holdTimerResetCh
|
||||||
@ -951,9 +1010,9 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s := h.fsm.pConf.GracefulRestart.State; s.Enabled && s.NotificationEnabled && body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET {
|
if s := h.fsm.pConf.GracefulRestart.State; s.Enabled && s.NotificationEnabled && body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET {
|
||||||
sendToErrorCh(FSM_HARD_RESET)
|
sendToStateReasonCh(FSM_HARD_RESET, m)
|
||||||
} else {
|
} else {
|
||||||
sendToErrorCh(FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_RECV, bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String())))
|
sendToStateReasonCh(FSM_NOTIFICATION_RECV, m)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -989,9 +1048,7 @@ func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode]
|
|||||||
if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y {
|
if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y {
|
||||||
items := make([]*bgp.CapAddPathTuple, 0, len(caps))
|
items := make([]*bgp.CapAddPathTuple, 0, len(caps))
|
||||||
for _, c := range caps {
|
for _, c := range caps {
|
||||||
for _, i := range c.(*bgp.CapAddPath).Tuples {
|
items = append(items, c.(*bgp.CapAddPath).Tuples...)
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)}
|
capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)}
|
||||||
}
|
}
|
||||||
@ -1030,7 +1087,7 @@ func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode]
|
|||||||
return capMap, negotiated
|
return capMap, negotiated
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
func (h *FSMHandler) opensent() (bgp.FSMState, *FsmStateReason) {
|
||||||
fsm := h.fsm
|
fsm := h.fsm
|
||||||
m := buildopen(fsm.gConf, fsm.pConf)
|
m := buildopen(fsm.gConf, fsm.pConf)
|
||||||
b, _ := m.Serialize()
|
b, _ := m.Serialize()
|
||||||
@ -1052,7 +1109,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
select {
|
select {
|
||||||
case <-h.t.Dying():
|
case <-h.t.Dying():
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return -1, FSM_DYING
|
return -1, NewFsmStateReason(FSM_DYING, nil, nil)
|
||||||
case conn, ok := <-fsm.connCh:
|
case conn, ok := <-fsm.connCh:
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
@ -1071,7 +1128,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Warn("graceful restart timer expired")
|
}).Warn("graceful restart timer expired")
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_RESTART_TIMER_EXPIRED, nil, nil)
|
||||||
}
|
}
|
||||||
case i, ok := <-h.msgCh.Out():
|
case i, ok := <-h.msgCh.Out():
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1086,8 +1143,8 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
body := m.Body.(*bgp.BGPOpen)
|
body := m.Body.(*bgp.BGPOpen)
|
||||||
peerAs, err := bgp.ValidateOpenMsg(body, fsm.pConf.Config.PeerAs)
|
peerAs, err := bgp.ValidateOpenMsg(body, fsm.pConf.Config.PeerAs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError))
|
m, _ := fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError))
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, m, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASN negotiation was skipped
|
// ASN negotiation was skipped
|
||||||
@ -1167,7 +1224,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
}).Warn("restart flag is not set")
|
}).Warn("restart flag is not set")
|
||||||
// send notification?
|
// send notification?
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC 4724 3
|
// RFC 4724 3
|
||||||
@ -1181,8 +1238,10 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Debug("peer is restarting, skipping sync process")
|
}).Debug("peer has restarted, skipping wait for EOR")
|
||||||
fsm.pConf.GracefulRestart.State.LocalRestarting = false
|
for i := range fsm.pConf.AfiSafis {
|
||||||
|
fsm.pConf.AfiSafis[i].MpGracefulRestart.State.EndOfRibReceived = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if fsm.pConf.GracefulRestart.Config.NotificationEnabled && cap.Flags&0x04 > 0 {
|
if fsm.pConf.GracefulRestart.Config.NotificationEnabled && cap.Flags&0x04 > 0 {
|
||||||
fsm.pConf.GracefulRestart.State.NotificationEnabled = true
|
fsm.pConf.GracefulRestart.State.NotificationEnabled = true
|
||||||
@ -1209,15 +1268,15 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
b, _ := msg.Serialize()
|
b, _ := msg.Serialize()
|
||||||
fsm.conn.Write(b)
|
fsm.conn.Write(b)
|
||||||
fsm.bgpMessageStateUpdate(msg.Header.Type, false)
|
fsm.bgpMessageStateUpdate(msg.Header.Type, false)
|
||||||
return bgp.BGP_FSM_OPENCONFIRM, FSM_OPEN_MSG_RECEIVED
|
return bgp.BGP_FSM_OPENCONFIRM, NewFsmStateReason(FSM_OPEN_MSG_RECEIVED, nil, nil)
|
||||||
} else {
|
} else {
|
||||||
// send notification?
|
// send notification?
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, nil, nil)
|
||||||
}
|
}
|
||||||
case *bgp.MessageError:
|
case *bgp.MessageError:
|
||||||
fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
|
m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, m, nil)
|
||||||
default:
|
default:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -1226,20 +1285,20 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Data": e.MsgData,
|
"Data": e.MsgData,
|
||||||
}).Panic("unknown msg type")
|
}).Panic("unknown msg type")
|
||||||
}
|
}
|
||||||
case err := <-h.errorCh:
|
case err := <-h.stateReasonCh:
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, err
|
return bgp.BGP_FSM_IDLE, &err
|
||||||
case <-holdTimer.C:
|
case <-holdTimer.C:
|
||||||
fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
|
m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
|
||||||
h.t.Kill(nil)
|
h.t.Kill(nil)
|
||||||
return bgp.BGP_FSM_IDLE, FSM_HOLD_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_HOLD_TIMER_EXPIRED, m, nil)
|
||||||
case stateOp := <-fsm.adminStateCh:
|
case stateOp := <-fsm.adminStateCh:
|
||||||
err := h.changeAdminState(stateOp.State)
|
err := h.changeAdminState(stateOp.State)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch stateOp.State {
|
switch stateOp.State {
|
||||||
case ADMIN_STATE_DOWN:
|
case ADMIN_STATE_DOWN:
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_ADMIN_DOWN
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_ADMIN_DOWN, m, nil)
|
||||||
case ADMIN_STATE_UP:
|
case ADMIN_STATE_UP:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -1265,7 +1324,7 @@ func keepaliveTicker(fsm *FSM) *time.Ticker {
|
|||||||
return time.NewTicker(sec)
|
return time.NewTicker(sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
|
func (h *FSMHandler) openconfirm() (bgp.FSMState, *FsmStateReason) {
|
||||||
fsm := h.fsm
|
fsm := h.fsm
|
||||||
ticker := keepaliveTicker(fsm)
|
ticker := keepaliveTicker(fsm)
|
||||||
h.msgCh = channels.NewInfiniteChannel()
|
h.msgCh = channels.NewInfiniteChannel()
|
||||||
@ -1286,7 +1345,7 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
|
|||||||
select {
|
select {
|
||||||
case <-h.t.Dying():
|
case <-h.t.Dying():
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return -1, FSM_DYING
|
return -1, NewFsmStateReason(FSM_DYING, nil, nil)
|
||||||
case conn, ok := <-fsm.connCh:
|
case conn, ok := <-fsm.connCh:
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
@ -1305,7 +1364,7 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
|
|||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Warn("graceful restart timer expired")
|
}).Warn("graceful restart timer expired")
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_RESTART_TIMER_EXPIRED, nil, nil)
|
||||||
}
|
}
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
m := bgp.NewBGPKeepAliveMessage()
|
m := bgp.NewBGPKeepAliveMessage()
|
||||||
@ -1322,14 +1381,14 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
|
|||||||
case *bgp.BGPMessage:
|
case *bgp.BGPMessage:
|
||||||
m := e.MsgData.(*bgp.BGPMessage)
|
m := e.MsgData.(*bgp.BGPMessage)
|
||||||
if m.Header.Type == bgp.BGP_MSG_KEEPALIVE {
|
if m.Header.Type == bgp.BGP_MSG_KEEPALIVE {
|
||||||
return bgp.BGP_FSM_ESTABLISHED, FSM_OPEN_MSG_NEGOTIATED
|
return bgp.BGP_FSM_ESTABLISHED, NewFsmStateReason(FSM_OPEN_MSG_NEGOTIATED, nil, nil)
|
||||||
}
|
}
|
||||||
// send notification ?
|
// send notification ?
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, nil, nil)
|
||||||
case *bgp.MessageError:
|
case *bgp.MessageError:
|
||||||
fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
|
m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError))
|
||||||
return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_INVALID_MSG, m, nil)
|
||||||
default:
|
default:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -1338,20 +1397,20 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Data": e.MsgData,
|
"Data": e.MsgData,
|
||||||
}).Panic("unknown msg type")
|
}).Panic("unknown msg type")
|
||||||
}
|
}
|
||||||
case err := <-h.errorCh:
|
case err := <-h.stateReasonCh:
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, err
|
return bgp.BGP_FSM_IDLE, &err
|
||||||
case <-holdTimer.C:
|
case <-holdTimer.C:
|
||||||
fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
|
m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired")
|
||||||
h.t.Kill(nil)
|
h.t.Kill(nil)
|
||||||
return bgp.BGP_FSM_IDLE, FSM_HOLD_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_HOLD_TIMER_EXPIRED, m, nil)
|
||||||
case stateOp := <-fsm.adminStateCh:
|
case stateOp := <-fsm.adminStateCh:
|
||||||
err := h.changeAdminState(stateOp.State)
|
err := h.changeAdminState(stateOp.State)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch stateOp.State {
|
switch stateOp.State {
|
||||||
case ADMIN_STATE_DOWN:
|
case ADMIN_STATE_DOWN:
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
return bgp.BGP_FSM_IDLE, FSM_ADMIN_DOWN
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_ADMIN_DOWN, nil, nil)
|
||||||
case ADMIN_STATE_UP:
|
case ADMIN_STATE_UP:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -1392,7 +1451,7 @@ func (h *FSMHandler) sendMessageloop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))); err != nil {
|
if err := conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))); err != nil {
|
||||||
h.errorCh <- FSM_WRITE_FAILED
|
h.stateReasonCh <- *NewFsmStateReason(FSM_WRITE_FAILED, nil, nil)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return fmt.Errorf("failed to set write deadline")
|
return fmt.Errorf("failed to set write deadline")
|
||||||
}
|
}
|
||||||
@ -1404,7 +1463,7 @@ func (h *FSMHandler) sendMessageloop() error {
|
|||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
"Data": err,
|
"Data": err,
|
||||||
}).Warn("failed to send")
|
}).Warn("failed to send")
|
||||||
h.errorCh <- FSM_WRITE_FAILED
|
h.stateReasonCh <- *NewFsmStateReason(FSM_WRITE_FAILED, nil, nil)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return fmt.Errorf("closed")
|
return fmt.Errorf("closed")
|
||||||
}
|
}
|
||||||
@ -1434,7 +1493,7 @@ func (h *FSMHandler) sendMessageloop() error {
|
|||||||
"Data": body.Data,
|
"Data": body.Data,
|
||||||
}).Warn("sent notification")
|
}).Warn("sent notification")
|
||||||
}
|
}
|
||||||
h.errorCh <- FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_SENT, bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String()))
|
h.stateReasonCh <- *NewFsmStateReason(FSM_NOTIFICATION_SENT, m, nil)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return fmt.Errorf("closed")
|
return fmt.Errorf("closed")
|
||||||
case bgp.BGP_MSG_UPDATE:
|
case bgp.BGP_MSG_UPDATE:
|
||||||
@ -1499,7 +1558,7 @@ func (h *FSMHandler) recvMessageloop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
|
func (h *FSMHandler) established() (bgp.FSMState, *FsmStateReason) {
|
||||||
fsm := h.fsm
|
fsm := h.fsm
|
||||||
h.conn = fsm.conn
|
h.conn = fsm.conn
|
||||||
h.t.Go(h.sendMessageloop)
|
h.t.Go(h.sendMessageloop)
|
||||||
@ -1518,7 +1577,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-h.t.Dying():
|
case <-h.t.Dying():
|
||||||
return -1, FSM_DYING
|
return -1, NewFsmStateReason(FSM_DYING, nil, nil)
|
||||||
case conn, ok := <-fsm.connCh:
|
case conn, ok := <-fsm.connCh:
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
@ -1529,11 +1588,14 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
|
|||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
}).Warn("Closed an accepted connection")
|
}).Warn("Closed an accepted connection")
|
||||||
case err := <-h.errorCh:
|
case err := <-h.stateReasonCh:
|
||||||
h.conn.Close()
|
h.conn.Close()
|
||||||
h.t.Kill(nil)
|
h.t.Kill(nil)
|
||||||
if s := fsm.pConf.GracefulRestart.State; s.Enabled && ((s.NotificationEnabled && strings.HasPrefix(string(err), FSM_NOTIFICATION_RECV)) || err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) {
|
if s := fsm.pConf.GracefulRestart.State; s.Enabled &&
|
||||||
err = FSM_GRACEFUL_RESTART
|
(s.NotificationEnabled && err.Type == FSM_NOTIFICATION_RECV ||
|
||||||
|
err.Type == FSM_READ_FAILED ||
|
||||||
|
err.Type == FSM_WRITE_FAILED) {
|
||||||
|
err = *NewFsmStateReason(FSM_GRACEFUL_RESTART, nil, nil)
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
@ -1541,7 +1603,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
|
|||||||
}).Info("peer graceful restart")
|
}).Info("peer graceful restart")
|
||||||
fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second)
|
fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second)
|
||||||
}
|
}
|
||||||
return bgp.BGP_FSM_IDLE, err
|
return bgp.BGP_FSM_IDLE, &err
|
||||||
case <-holdTimer.C:
|
case <-holdTimer.C:
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
@ -1550,7 +1612,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
|
|||||||
}).Warn("hold timer expired")
|
}).Warn("hold timer expired")
|
||||||
m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil)
|
m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil)
|
||||||
h.outgoing.In() <- &FsmOutgoingMsg{Notification: m}
|
h.outgoing.In() <- &FsmOutgoingMsg{Notification: m}
|
||||||
return bgp.BGP_FSM_IDLE, FSM_HOLD_TIMER_EXPIRED
|
return bgp.BGP_FSM_IDLE, NewFsmStateReason(FSM_HOLD_TIMER_EXPIRED, m, nil)
|
||||||
case <-h.holdTimerResetCh:
|
case <-h.holdTimerResetCh:
|
||||||
if fsm.pConf.Timers.State.NegotiatedHoldTime != 0 {
|
if fsm.pConf.Timers.State.NegotiatedHoldTime != 0 {
|
||||||
holdTimer.Reset(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
|
holdTimer.Reset(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
|
||||||
@ -1573,9 +1635,9 @@ func (h *FSMHandler) loop() error {
|
|||||||
ch := make(chan bgp.FSMState)
|
ch := make(chan bgp.FSMState)
|
||||||
oldState := fsm.state
|
oldState := fsm.state
|
||||||
|
|
||||||
|
var reason *FsmStateReason
|
||||||
f := func() error {
|
f := func() error {
|
||||||
nextState := bgp.FSMState(-1)
|
nextState := bgp.FSMState(-1)
|
||||||
var reason FsmStateReason
|
|
||||||
switch fsm.state {
|
switch fsm.state {
|
||||||
case bgp.BGP_FSM_IDLE:
|
case bgp.BGP_FSM_IDLE:
|
||||||
nextState, reason = h.idle()
|
nextState, reason = h.idle()
|
||||||
@ -1611,14 +1673,16 @@ func (h *FSMHandler) loop() error {
|
|||||||
// The main goroutine sent the notificaiton due to
|
// The main goroutine sent the notificaiton due to
|
||||||
// deconfiguration or something.
|
// deconfiguration or something.
|
||||||
reason := fsm.reason
|
reason := fsm.reason
|
||||||
if fsm.h.sentNotification != "" {
|
if fsm.h.sentNotification != nil {
|
||||||
reason = FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_SENT, fsm.h.sentNotification))
|
reason.Type = FSM_NOTIFICATION_SENT
|
||||||
|
reason.PeerDownReason = PEER_DOWN_BY_LOCAL
|
||||||
|
reason.BGPNotification = fsm.h.sentNotification
|
||||||
}
|
}
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Peer",
|
"Topic": "Peer",
|
||||||
"Key": fsm.pConf.State.NeighborAddress,
|
"Key": fsm.pConf.State.NeighborAddress,
|
||||||
"State": fsm.state.String(),
|
"State": fsm.state.String(),
|
||||||
"Reason": reason,
|
"Reason": reason.String(),
|
||||||
}).Info("Peer Down")
|
}).Info("Peer Down")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1630,13 +1694,13 @@ func (h *FSMHandler) loop() error {
|
|||||||
|
|
||||||
// under zero means that tomb.Dying()
|
// under zero means that tomb.Dying()
|
||||||
if nextState >= bgp.BGP_FSM_IDLE {
|
if nextState >= bgp.BGP_FSM_IDLE {
|
||||||
e := &FsmMsg{
|
h.stateCh <- &FsmMsg{
|
||||||
MsgType: FSM_MSG_STATE_CHANGE,
|
MsgType: FSM_MSG_STATE_CHANGE,
|
||||||
MsgSrc: fsm.pConf.State.NeighborAddress,
|
MsgSrc: fsm.pConf.State.NeighborAddress,
|
||||||
MsgData: nextState,
|
MsgData: nextState,
|
||||||
Version: h.fsm.version,
|
StateReason: reason,
|
||||||
|
Version: h.fsm.version,
|
||||||
}
|
}
|
||||||
h.stateCh <- e
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
27
vendor/github.com/osrg/gobgp/server/mrt.go
generated
vendored
27
vendor/github.com/osrg/gobgp/server/mrt.go
generated
vendored
@ -21,11 +21,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
"github.com/osrg/gobgp/packet/mrt"
|
"github.com/osrg/gobgp/packet/mrt"
|
||||||
"github.com/osrg/gobgp/table"
|
"github.com/osrg/gobgp/table"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -88,6 +89,9 @@ func (m *mrtWriter) loop() error {
|
|||||||
msg := make([]*mrt.MRTMessage, 0, 1)
|
msg := make([]*mrt.MRTMessage, 0, 1)
|
||||||
switch e := ev.(type) {
|
switch e := ev.(type) {
|
||||||
case *WatchEventUpdate:
|
case *WatchEventUpdate:
|
||||||
|
if e.Init {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
mp := mrt.NewBGP4MPMessage(e.PeerAS, e.LocalAS, 0, e.PeerAddress.String(), e.LocalAddress.String(), e.FourBytesAs, nil)
|
mp := mrt.NewBGP4MPMessage(e.PeerAS, e.LocalAS, 0, e.PeerAddress.String(), e.LocalAddress.String(), e.FourBytesAs, nil)
|
||||||
mp.BGPMessagePayload = e.Payload
|
mp.BGPMessagePayload = e.Payload
|
||||||
isAddPath := e.Neighbor.IsAddPathReceiveEnabled(e.PathList[0].GetRouteFamily())
|
isAddPath := e.Neighbor.IsAddPathReceiveEnabled(e.PathList[0].GetRouteFamily())
|
||||||
@ -111,12 +115,16 @@ func (m *mrtWriter) loop() error {
|
|||||||
}
|
}
|
||||||
case *WatchEventTable:
|
case *WatchEventTable:
|
||||||
t := uint32(time.Now().Unix())
|
t := uint32(time.Now().Unix())
|
||||||
peers := make([]*mrt.Peer, 0, len(e.Neighbor))
|
|
||||||
|
peers := make([]*mrt.Peer, 1, len(e.Neighbor)+1)
|
||||||
|
// Adding dummy Peer record for locally generated routes
|
||||||
|
peers[0] = mrt.NewPeer("0.0.0.0", "0.0.0.0", 0, true)
|
||||||
neighborMap := make(map[string]*config.Neighbor)
|
neighborMap := make(map[string]*config.Neighbor)
|
||||||
for _, pconf := range e.Neighbor {
|
for _, pconf := range e.Neighbor {
|
||||||
peers = append(peers, mrt.NewPeer(pconf.State.RemoteRouterId, pconf.State.NeighborAddress, pconf.Config.PeerAs, true))
|
peers = append(peers, mrt.NewPeer(pconf.State.RemoteRouterId, pconf.State.NeighborAddress, pconf.Config.PeerAs, true))
|
||||||
neighborMap[pconf.State.NeighborAddress] = pconf
|
neighborMap[pconf.State.NeighborAddress] = pconf
|
||||||
}
|
}
|
||||||
|
|
||||||
if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(e.RouterId, "", peers)); err != nil {
|
if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(e.RouterId, "", peers)); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "mrt",
|
"Topic": "mrt",
|
||||||
@ -174,11 +182,10 @@ func (m *mrtWriter) loop() error {
|
|||||||
entries := make([]*mrt.RibEntry, 0, len(pathList))
|
entries := make([]*mrt.RibEntry, 0, len(pathList))
|
||||||
entriesAddPath := make([]*mrt.RibEntry, 0, len(pathList))
|
entriesAddPath := make([]*mrt.RibEntry, 0, len(pathList))
|
||||||
for _, path := range pathList {
|
for _, path := range pathList {
|
||||||
if path.IsLocal() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
isAddPath := false
|
isAddPath := false
|
||||||
if neighbor, ok := neighborMap[path.GetSource().Address.String()]; ok {
|
if path.IsLocal() {
|
||||||
|
isAddPath = true
|
||||||
|
} else if neighbor, ok := neighborMap[path.GetSource().Address.String()]; ok {
|
||||||
isAddPath = neighbor.IsAddPathReceiveEnabled(path.GetRouteFamily())
|
isAddPath = neighbor.IsAddPathReceiveEnabled(path.GetRouteFamily())
|
||||||
}
|
}
|
||||||
if !isAddPath {
|
if !isAddPath {
|
||||||
@ -385,12 +392,12 @@ func (m *mrtManager) enable(c *config.MrtConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrtManager) disable(c *config.MrtConfig) error {
|
func (m *mrtManager) disable(c *config.MrtConfig) error {
|
||||||
if w, ok := m.writer[c.FileName]; !ok {
|
w, ok := m.writer[c.FileName]
|
||||||
|
if !ok {
|
||||||
return fmt.Errorf("%s doesn't exists", c.FileName)
|
return fmt.Errorf("%s doesn't exists", c.FileName)
|
||||||
} else {
|
|
||||||
w.Stop()
|
|
||||||
delete(m.writer, c.FileName)
|
|
||||||
}
|
}
|
||||||
|
w.Stop()
|
||||||
|
delete(m.writer, c.FileName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
283
vendor/github.com/osrg/gobgp/server/peer.go
generated
vendored
283
vendor/github.com/osrg/gobgp/server/peer.go
generated
vendored
@ -42,8 +42,8 @@ type PeerGroup struct {
|
|||||||
func NewPeerGroup(c *config.PeerGroup) *PeerGroup {
|
func NewPeerGroup(c *config.PeerGroup) *PeerGroup {
|
||||||
return &PeerGroup{
|
return &PeerGroup{
|
||||||
Conf: c,
|
Conf: c,
|
||||||
members: make(map[string]config.Neighbor, 0),
|
members: make(map[string]config.Neighbor),
|
||||||
dynamicNeighbors: make(map[string]*config.DynamicNeighbor, 0),
|
dynamicNeighbors: make(map[string]*config.DynamicNeighbor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, p
|
|||||||
peer.tableId = table.GLOBAL_RIB_NAME
|
peer.tableId = table.GLOBAL_RIB_NAME
|
||||||
}
|
}
|
||||||
rfs, _ := config.AfiSafis(conf.AfiSafis).ToRfList()
|
rfs, _ := config.AfiSafis(conf.AfiSafis).ToRfList()
|
||||||
peer.adjRibIn = table.NewAdjRib(peer.ID(), rfs)
|
peer.adjRibIn = table.NewAdjRib(rfs)
|
||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +182,14 @@ func (peer *Peer) configuredRFlist() []bgp.RouteFamily {
|
|||||||
return rfs
|
return rfs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (peer *Peer) negotiatedRFList() []bgp.RouteFamily {
|
||||||
|
l := make([]bgp.RouteFamily, 0, len(peer.fsm.rfMap))
|
||||||
|
for family, _ := range peer.fsm.rfMap {
|
||||||
|
l = append(l, family)
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func (peer *Peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily {
|
func (peer *Peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily {
|
||||||
if peer.fsm.pConf.Config.Vrf != "" {
|
if peer.fsm.pConf.Config.Vrf != "" {
|
||||||
fs := make([]bgp.RouteFamily, 0, len(families))
|
fs := make([]bgp.RouteFamily, 0, len(families))
|
||||||
@ -285,7 +293,7 @@ func (peer *Peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
|
|||||||
for i, p := range paths {
|
for i, p := range paths {
|
||||||
doStale := true
|
doStale := true
|
||||||
for _, c := range p.GetCommunities() {
|
for _, c := range p.GetCommunities() {
|
||||||
if c == bgp.COMMUNITY_NO_LLGR {
|
if c == uint32(bgp.COMMUNITY_NO_LLGR) {
|
||||||
doStale = false
|
doStale = false
|
||||||
p = p.Clone(true)
|
p = p.Clone(true)
|
||||||
break
|
break
|
||||||
@ -293,7 +301,7 @@ func (peer *Peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
|
|||||||
}
|
}
|
||||||
if doStale {
|
if doStale {
|
||||||
p = p.Clone(false)
|
p = p.Clone(false)
|
||||||
p.SetCommunities([]uint32{bgp.COMMUNITY_LLGR_STALE}, false)
|
p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
|
||||||
}
|
}
|
||||||
paths[i] = p
|
paths[i] = p
|
||||||
}
|
}
|
||||||
@ -309,109 +317,6 @@ func (peer *Peer) stopPeerRestarting() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path {
|
|
||||||
return peer.adjRibIn.PathList(rfList, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) filterpath(path, old *table.Path) *table.Path {
|
|
||||||
// Special handling for RTM NLRI.
|
|
||||||
if path != nil && path.GetRouteFamily() == bgp.RF_RTC_UC && !path.IsWithdraw {
|
|
||||||
// If the given "path" is locally generated and the same with "old", we
|
|
||||||
// assumes "path" was already sent before. This assumption avoids the
|
|
||||||
// infinite UPDATE loop between Route Reflector and its clients.
|
|
||||||
if path.IsLocal() && path == old {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Peer",
|
|
||||||
"Key": peer.fsm.pConf.State.NeighborAddress,
|
|
||||||
"Path": path,
|
|
||||||
}).Debug("given rtm nlri is already sent, skipping to advertise")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if old != nil && old.IsLocal() {
|
|
||||||
// We assumes VRF with the specific RT is deleted.
|
|
||||||
path = old.Clone(true)
|
|
||||||
} else if peer.isRouteReflectorClient() {
|
|
||||||
// We need to send the path even if the peer is originator of the
|
|
||||||
// path in order to signal that the client should distribute route
|
|
||||||
// with the given RT.
|
|
||||||
} else {
|
|
||||||
// We send a path even if it is not the best path. See comments in
|
|
||||||
// (*Destination) GetChanges().
|
|
||||||
dst := peer.localRib.GetDestination(path)
|
|
||||||
path = nil
|
|
||||||
for _, p := range dst.GetKnownPathList(peer.TableID()) {
|
|
||||||
// Just take care not to send back.
|
|
||||||
if peer.ID() != p.GetSource().Address.String() {
|
|
||||||
path = p
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only allow vpnv4 and vpnv6 paths to be advertised to VRFed neighbors.
|
|
||||||
// also check we can import this path using table.CanImportToVrf()
|
|
||||||
// if we can, make it local path by calling (*Path).ToLocal()
|
|
||||||
if path != nil && peer.fsm.pConf.Config.Vrf != "" {
|
|
||||||
if f := path.GetRouteFamily(); f != bgp.RF_IPv4_VPN && f != bgp.RF_IPv6_VPN {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
vrf := peer.localRib.Vrfs[peer.fsm.pConf.Config.Vrf]
|
|
||||||
if table.CanImportToVrf(vrf, path) {
|
|
||||||
path = path.ToLocal()
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace-peer-as handling
|
|
||||||
if path != nil && !path.IsWithdraw && peer.fsm.pConf.AsPathOptions.State.ReplacePeerAs {
|
|
||||||
path = path.ReplaceAS(peer.fsm.pConf.Config.LocalAs, peer.fsm.pConf.Config.PeerAs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if path = filterpath(peer, path, old); path == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
path = table.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf, peer.fsm.peerInfo, path)
|
|
||||||
|
|
||||||
options := &table.PolicyOptions{
|
|
||||||
Info: peer.fsm.peerInfo,
|
|
||||||
}
|
|
||||||
path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options)
|
|
||||||
// When 'path' is filtered (path == nil), check 'old' has been sent to this peer.
|
|
||||||
// If it has, send withdrawal to the peer.
|
|
||||||
if path == nil && old != nil {
|
|
||||||
o := peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, old, options)
|
|
||||||
if o != nil {
|
|
||||||
path = old.Clone(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draft-uttaro-idr-bgp-persistence-02
|
|
||||||
// 4.3. Processing LLGR_STALE Routes
|
|
||||||
//
|
|
||||||
// The route SHOULD NOT be advertised to any neighbor from which the
|
|
||||||
// Long-lived Graceful Restart Capability has not been received. The
|
|
||||||
// exception is described in the Optional Partial Deployment
|
|
||||||
// Procedure section (Section 4.7). Note that this requirement
|
|
||||||
// implies that such routes should be withdrawn from any such neighbor.
|
|
||||||
if path != nil && !path.IsWithdraw && !peer.isLLGREnabledFamily(path.GetRouteFamily()) && path.IsLLGRStale() {
|
|
||||||
// we send unnecessary withdrawn even if we didn't
|
|
||||||
// sent the route.
|
|
||||||
path = path.Clone(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove local-pref attribute
|
|
||||||
// we should do this after applying export policy since policy may
|
|
||||||
// set local-preference
|
|
||||||
if path != nil && !peer.isIBGPPeer() && !peer.isRouteServerClient() {
|
|
||||||
path.RemoveLocalPref()
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
|
func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
|
||||||
if peer.ID() != path.GetSource().Address.String() {
|
if peer.ID() != path.GetSource().Address.String() {
|
||||||
return path
|
return path
|
||||||
@ -447,86 +352,6 @@ func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) {
|
|
||||||
pathList := []*table.Path{}
|
|
||||||
filtered := []*table.Path{}
|
|
||||||
for _, family := range peer.toGlobalFamilies(rfList) {
|
|
||||||
pl := func() []*table.Path {
|
|
||||||
if peer.isAddPathSendEnabled(family) {
|
|
||||||
return peer.localRib.GetPathList(peer.TableID(), []bgp.RouteFamily{family})
|
|
||||||
}
|
|
||||||
return peer.localRib.GetBestPathList(peer.TableID(), []bgp.RouteFamily{family})
|
|
||||||
}()
|
|
||||||
for _, path := range pl {
|
|
||||||
if p := peer.filterpath(path, nil); p != nil {
|
|
||||||
pathList = append(pathList, p)
|
|
||||||
} else {
|
|
||||||
filtered = append(filtered, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if peer.isGracefulRestartEnabled() {
|
|
||||||
for _, family := range rfList {
|
|
||||||
pathList = append(pathList, table.NewEOR(family))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pathList, filtered
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) processOutgoingPaths(paths, olds []*table.Path) []*table.Path {
|
|
||||||
if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if peer.fsm.pConf.GracefulRestart.State.LocalRestarting {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Peer",
|
|
||||||
"Key": peer.fsm.pConf.State.NeighborAddress,
|
|
||||||
}).Debug("now syncing, suppress sending updates")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
outgoing := make([]*table.Path, 0, len(paths))
|
|
||||||
|
|
||||||
for idx, path := range paths {
|
|
||||||
var old *table.Path
|
|
||||||
if olds != nil {
|
|
||||||
old = olds[idx]
|
|
||||||
}
|
|
||||||
if p := peer.filterpath(path, old); p != nil {
|
|
||||||
outgoing = append(outgoing, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return outgoing
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) handleRouteRefresh(e *FsmMsg) []*table.Path {
|
|
||||||
m := e.MsgData.(*bgp.BGPMessage)
|
|
||||||
rr := m.Body.(*bgp.BGPRouteRefresh)
|
|
||||||
rf := bgp.AfiSafiToRouteFamily(rr.AFI, rr.SAFI)
|
|
||||||
if _, ok := peer.fsm.rfMap[rf]; !ok {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Peer",
|
|
||||||
"Key": peer.ID(),
|
|
||||||
"Data": rf,
|
|
||||||
}).Warn("Route family isn't supported")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if _, ok := peer.fsm.capMap[bgp.BGP_CAP_ROUTE_REFRESH]; !ok {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Peer",
|
|
||||||
"Key": peer.ID(),
|
|
||||||
}).Warn("ROUTE_REFRESH received but the capability wasn't advertised")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rfList := []bgp.RouteFamily{rf}
|
|
||||||
accepted, filtered := peer.getBestFromLocal(rfList)
|
|
||||||
for _, path := range filtered {
|
|
||||||
path.IsWithdraw = true
|
|
||||||
accepted = append(accepted, path)
|
|
||||||
}
|
|
||||||
return accepted
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage {
|
func (peer *Peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage {
|
||||||
if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 {
|
if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 {
|
||||||
count := peer.adjRibIn.Count([]bgp.RouteFamily{k})
|
count := peer.adjRibIn.Count([]bgp.RouteFamily{k})
|
||||||
@ -597,12 +422,6 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg
|
|||||||
}).Debug("received update")
|
}).Debug("received update")
|
||||||
peer.fsm.pConf.Timers.State.UpdateRecvTime = time.Now().Unix()
|
peer.fsm.pConf.Timers.State.UpdateRecvTime = time.Now().Unix()
|
||||||
if len(e.PathList) > 0 {
|
if len(e.PathList) > 0 {
|
||||||
peer.adjRibIn.Update(e.PathList)
|
|
||||||
for _, af := range peer.fsm.pConf.AfiSafis {
|
|
||||||
if msg := peer.doPrefixLimit(af.State.Family, &af.PrefixLimit.Config); msg != nil {
|
|
||||||
return nil, nil, msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paths := make([]*table.Path, 0, len(e.PathList))
|
paths := make([]*table.Path, 0, len(e.PathList))
|
||||||
eor := []bgp.RouteFamily{}
|
eor := []bgp.RouteFamily{}
|
||||||
for _, path := range e.PathList {
|
for _, path := range e.PathList {
|
||||||
@ -616,10 +435,22 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg
|
|||||||
eor = append(eor, family)
|
eor = append(eor, family)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path.Filtered(peer.ID()) != table.POLICY_DIRECTION_IN {
|
// RFC4271 9.1.2 Phase 2: Route Selection
|
||||||
paths = append(paths, path)
|
//
|
||||||
} else {
|
// If the AS_PATH attribute of a BGP route contains an AS loop, the BGP
|
||||||
paths = append(paths, path.Clone(true))
|
// route should be excluded from the Phase 2 decision function.
|
||||||
|
if aspath := path.GetAsPath(); aspath != nil {
|
||||||
|
if hasOwnASLoop(peer.fsm.peerInfo.LocalAS, int(peer.fsm.pConf.AsPathOptions.Config.AllowOwnAs), aspath) {
|
||||||
|
path.SetAsLooped(true)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paths = append(paths, path)
|
||||||
|
}
|
||||||
|
peer.adjRibIn.Update(e.PathList)
|
||||||
|
for _, af := range peer.fsm.pConf.AfiSafis {
|
||||||
|
if msg := peer.doPrefixLimit(af.State.Family, &af.PrefixLimit.Config); msg != nil {
|
||||||
|
return nil, nil, msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return paths, eor, nil
|
return paths, eor, nil
|
||||||
@ -631,8 +462,8 @@ func (peer *Peer) startFSMHandler(incoming *channels.InfiniteChannel, stateCh ch
|
|||||||
peer.fsm.h = NewFSMHandler(peer.fsm, incoming, stateCh, peer.outgoing)
|
peer.fsm.h = NewFSMHandler(peer.fsm, incoming, stateCh, peer.outgoing)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) StaleAll(rfList []bgp.RouteFamily) {
|
func (peer *Peer) StaleAll(rfList []bgp.RouteFamily) []*table.Path {
|
||||||
peer.adjRibIn.StaleAll(rfList)
|
return peer.adjRibIn.StaleAll(rfList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) PassConn(conn *net.TCPConn) {
|
func (peer *Peer) PassConn(conn *net.TCPConn) {
|
||||||
@ -647,58 +478,6 @@ func (peer *Peer) PassConn(conn *net.TCPConn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) ToConfig(getAdvertised bool) *config.Neighbor {
|
|
||||||
// create copy which can be access to without mutex
|
|
||||||
conf := *peer.fsm.pConf
|
|
||||||
|
|
||||||
conf.AfiSafis = make([]config.AfiSafi, len(peer.fsm.pConf.AfiSafis))
|
|
||||||
for i, af := range peer.fsm.pConf.AfiSafis {
|
|
||||||
conf.AfiSafis[i] = af
|
|
||||||
conf.AfiSafis[i].AddPaths.State.Receive = peer.isAddPathReceiveEnabled(af.State.Family)
|
|
||||||
if peer.isAddPathSendEnabled(af.State.Family) {
|
|
||||||
conf.AfiSafis[i].AddPaths.State.SendMax = af.AddPaths.State.SendMax
|
|
||||||
} else {
|
|
||||||
conf.AfiSafis[i].AddPaths.State.SendMax = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteCap := make([]bgp.ParameterCapabilityInterface, 0, len(peer.fsm.capMap))
|
|
||||||
for _, caps := range peer.fsm.capMap {
|
|
||||||
for _, m := range caps {
|
|
||||||
// need to copy all values here
|
|
||||||
buf, _ := m.Serialize()
|
|
||||||
c, _ := bgp.DecodeCapability(buf)
|
|
||||||
remoteCap = append(remoteCap, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conf.State.RemoteCapabilityList = remoteCap
|
|
||||||
conf.State.LocalCapabilityList = capabilitiesFromConfig(peer.fsm.pConf)
|
|
||||||
|
|
||||||
conf.State.SessionState = config.IntToSessionStateMap[int(peer.fsm.state)]
|
|
||||||
conf.State.AdminState = config.IntToAdminStateMap[int(peer.fsm.adminState)]
|
|
||||||
|
|
||||||
if peer.fsm.state == bgp.BGP_FSM_ESTABLISHED {
|
|
||||||
rfList := peer.configuredRFlist()
|
|
||||||
if getAdvertised {
|
|
||||||
pathList, filtered := peer.getBestFromLocal(rfList)
|
|
||||||
conf.State.AdjTable.Advertised = uint32(len(pathList))
|
|
||||||
conf.State.AdjTable.Filtered = uint32(len(filtered))
|
|
||||||
} else {
|
|
||||||
conf.State.AdjTable.Advertised = 0
|
|
||||||
}
|
|
||||||
conf.State.AdjTable.Received = uint32(peer.adjRibIn.Count(rfList))
|
|
||||||
conf.State.AdjTable.Accepted = uint32(peer.adjRibIn.Accepted(rfList))
|
|
||||||
|
|
||||||
conf.Transport.State.LocalAddress, conf.Transport.State.LocalPort = peer.fsm.LocalHostPort()
|
|
||||||
_, conf.Transport.State.RemotePort = peer.fsm.RemoteHostPort()
|
|
||||||
buf, _ := peer.fsm.recvOpen.Serialize()
|
|
||||||
// need to copy all values here
|
|
||||||
conf.State.ReceivedOpenMessage, _ = bgp.ParseBGPMessage(buf)
|
|
||||||
conf.State.RemoteRouterId = peer.fsm.peerInfo.ID.To4().String()
|
|
||||||
}
|
|
||||||
return &conf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (peer *Peer) DropAll(rfList []bgp.RouteFamily) {
|
func (peer *Peer) DropAll(rfList []bgp.RouteFamily) {
|
||||||
peer.adjRibIn.Drop(rfList)
|
peer.adjRibIn.Drop(rfList)
|
||||||
}
|
}
|
||||||
|
|||||||
24
vendor/github.com/osrg/gobgp/server/rpki.go
generated
vendored
24
vendor/github.com/osrg/gobgp/server/rpki.go
generated
vendored
@ -112,6 +112,10 @@ func NewROAManager(as uint32) (*roaManager, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *roaManager) enabled() bool {
|
||||||
|
return len(c.clientMap) != 0
|
||||||
|
}
|
||||||
|
|
||||||
func (m *roaManager) SetAS(as uint32) error {
|
func (m *roaManager) SetAS(as uint32) error {
|
||||||
if m.AS != 0 {
|
if m.AS != 0 {
|
||||||
return fmt.Errorf("AS was already configured")
|
return fmt.Errorf("AS was already configured")
|
||||||
@ -570,21 +574,15 @@ func ValidatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathA
|
|||||||
return validation
|
return validation
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *roaManager) validate(pathList []*table.Path) {
|
func (c *roaManager) validate(path *table.Path) *table.Validation {
|
||||||
if len(c.clientMap) == 0 {
|
if len(c.clientMap) == 0 || path.IsWithdraw || path.IsEOR() {
|
||||||
// RPKI isn't enabled
|
// RPKI isn't enabled or invalid path
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
if tree, ok := c.Roas[path.GetRouteFamily()]; ok {
|
||||||
for _, path := range pathList {
|
return ValidatePath(c.AS, tree, path.GetNlri().String(), path.GetAsPath())
|
||||||
if path.IsWithdraw || path.IsEOR() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if tree, ok := c.Roas[path.GetRouteFamily()]; ok {
|
|
||||||
v := ValidatePath(c.AS, tree, path.GetNlri().String(), path.GetAsPath())
|
|
||||||
path.SetValidation(v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type roaClient struct {
|
type roaClient struct {
|
||||||
|
|||||||
983
vendor/github.com/osrg/gobgp/server/server.go
generated
vendored
983
vendor/github.com/osrg/gobgp/server/server.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8
vendor/github.com/osrg/gobgp/server/sockopt_darwin.go
generated
vendored
8
vendor/github.com/osrg/gobgp/server/sockopt_darwin.go
generated
vendored
@ -39,19 +39,23 @@ func setsockoptIpTtl(fd int, family int, value int) error {
|
|||||||
|
|
||||||
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||||
fi, family, err := extractFileAndFamilyFromTCPListener(l)
|
fi, family, err := extractFileAndFamilyFromTCPListener(l)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||||
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
vendor/github.com/osrg/gobgp/server/sockopt_linux.go
generated
vendored
22
vendor/github.com/osrg/gobgp/server/sockopt_linux.go
generated
vendored
@ -32,10 +32,12 @@ const (
|
|||||||
type tcpmd5sig struct {
|
type tcpmd5sig struct {
|
||||||
ss_family uint16
|
ss_family uint16
|
||||||
ss [126]byte
|
ss [126]byte
|
||||||
pad1 uint16
|
// padding the struct
|
||||||
keylen uint16
|
_ uint16
|
||||||
pad2 uint32
|
keylen uint16
|
||||||
key [80]byte
|
// padding the struct
|
||||||
|
_ uint32
|
||||||
|
key [80]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTcpMD5Sig(address string, key string) (tcpmd5sig, error) {
|
func buildTcpMD5Sig(address string, key string) (tcpmd5sig, error) {
|
||||||
@ -66,10 +68,11 @@ func setsockoptTcpMD5Sig(fd int, address string, key string) error {
|
|||||||
|
|
||||||
func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||||
fi, _, err := extractFileAndFamilyFromTCPListener(l)
|
fi, _, err := extractFileAndFamilyFromTCPListener(l)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptTcpMD5Sig(int(fi.Fd()), address, key)
|
return setsockoptTcpMD5Sig(int(fi.Fd()), address, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,19 +88,21 @@ func setsockoptIpTtl(fd int, family int, value int) error {
|
|||||||
|
|
||||||
func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||||
fi, family, err := extractFileAndFamilyFromTCPListener(l)
|
fi, family, err := extractFileAndFamilyFromTCPListener(l)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||||
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
return setsockoptIpTtl(int(fi.Fd()), family, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,10 +118,11 @@ func setsockoptIpMinTtl(fd int, family int, value int) error {
|
|||||||
|
|
||||||
func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
|
func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||||
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
fi, family, err := extractFileAndFamilyFromTCPConn(conn)
|
||||||
defer fi.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
|
||||||
return setsockoptIpMinTtl(int(fi.Fd()), family, ttl)
|
return setsockoptIpMinTtl(int(fi.Fd()), family, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
430
vendor/github.com/osrg/gobgp/server/zclient.go
generated
vendored
430
vendor/github.com/osrg/gobgp/server/zclient.go
generated
vendored
@ -17,6 +17,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -30,176 +31,69 @@ import (
|
|||||||
"github.com/osrg/gobgp/zebra"
|
"github.com/osrg/gobgp/zebra"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pathList []*table.Path
|
// nexthopStateCache stores a map of nexthop IP to metric value. Especially,
|
||||||
|
// the metric value of math.MaxUint32 means the nexthop is unreachable.
|
||||||
|
type nexthopStateCache map[string]uint32
|
||||||
|
|
||||||
type nexthopTrackingManager struct {
|
func (m nexthopStateCache) applyToPathList(paths []*table.Path) []*table.Path {
|
||||||
dead chan struct{}
|
updated := make([]*table.Path, 0, len(paths))
|
||||||
nexthopCache map[string]struct{}
|
for _, path := range paths {
|
||||||
server *BgpServer
|
if path == nil || path.IsWithdraw {
|
||||||
delay int
|
continue
|
||||||
isScheduled bool
|
}
|
||||||
scheduledPathList map[string]pathList
|
metric, ok := m[path.GetNexthop().String()]
|
||||||
trigger chan struct{}
|
if !ok {
|
||||||
pathListCh chan pathList
|
continue
|
||||||
}
|
}
|
||||||
|
isNexthopInvalid := metric == math.MaxUint32
|
||||||
func newNexthopTrackingManager(server *BgpServer, delay int) *nexthopTrackingManager {
|
med, err := path.GetMed()
|
||||||
return &nexthopTrackingManager{
|
if err == nil && med == metric && path.IsNexthopInvalid == isNexthopInvalid {
|
||||||
dead: make(chan struct{}),
|
// If the nexthop state of the given path is already up to date,
|
||||||
nexthopCache: make(map[string]struct{}),
|
// skips this path.
|
||||||
server: server,
|
continue
|
||||||
delay: delay,
|
}
|
||||||
scheduledPathList: make(map[string]pathList, 0),
|
newPath := path.Clone(false)
|
||||||
trigger: make(chan struct{}),
|
if isNexthopInvalid {
|
||||||
pathListCh: make(chan pathList),
|
newPath.IsNexthopInvalid = true
|
||||||
|
} else {
|
||||||
|
newPath.IsNexthopInvalid = false
|
||||||
|
newPath.SetMed(int64(metric), true)
|
||||||
|
}
|
||||||
|
updated = append(updated, newPath)
|
||||||
}
|
}
|
||||||
|
return updated
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) stop() {
|
func (m nexthopStateCache) updateByNexthopUpdate(body *zebra.NexthopUpdateBody) (updated bool) {
|
||||||
close(m.pathListCh)
|
if len(body.Nexthops) == 0 {
|
||||||
close(m.trigger)
|
// If NEXTHOP_UPDATE message does not contain any nexthop, the given
|
||||||
close(m.dead)
|
// nexthop is unreachable.
|
||||||
}
|
if _, ok := m[body.Prefix.String()]; !ok {
|
||||||
|
// Zebra will send an empty NEXTHOP_UPDATE message as the fist
|
||||||
func (m *nexthopTrackingManager) isRegisteredNexthop(nexthop net.IP) bool {
|
// response for the NEXTHOP_REGISTER message. Here ignores it.
|
||||||
key := nexthop.String()
|
return false
|
||||||
_, ok := m.nexthopCache[key]
|
}
|
||||||
return ok
|
m[body.Prefix.String()] = math.MaxUint32 // means unreachable
|
||||||
}
|
} else {
|
||||||
|
m[body.Prefix.String()] = body.Metric
|
||||||
func (m *nexthopTrackingManager) registerNexthop(nexthop net.IP) bool {
|
|
||||||
key := nexthop.String()
|
|
||||||
if _, ok := m.nexthopCache[key]; ok {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
m.nexthopCache[key] = struct{}{}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) unregisterNexthop(nexthop net.IP) {
|
func (m nexthopStateCache) filterPathToRegister(paths []*table.Path) []*table.Path {
|
||||||
key := nexthop.String()
|
filteredPaths := make([]*table.Path, 0, len(paths))
|
||||||
delete(m.nexthopCache, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) appendPathList(paths pathList) {
|
|
||||||
if len(paths) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
path := paths[0]
|
|
||||||
|
|
||||||
m.scheduledPathList[path.GetNexthop().String()] = paths
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) calculateDelay(penalty int) int {
|
|
||||||
if penalty <= 950 {
|
|
||||||
return m.delay
|
|
||||||
}
|
|
||||||
|
|
||||||
delay := 8
|
|
||||||
for penalty > 950 {
|
|
||||||
delay += 8
|
|
||||||
penalty /= 2
|
|
||||||
}
|
|
||||||
return delay
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) triggerUpdatePathAfter(delay int) {
|
|
||||||
time.Sleep(time.Duration(delay) * time.Second)
|
|
||||||
|
|
||||||
m.trigger <- struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) loop() {
|
|
||||||
t := time.NewTicker(8 * time.Second)
|
|
||||||
defer t.Stop()
|
|
||||||
|
|
||||||
penalty := 0
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-m.dead:
|
|
||||||
return
|
|
||||||
|
|
||||||
case <-t.C:
|
|
||||||
penalty /= 2
|
|
||||||
|
|
||||||
case paths := <-m.pathListCh:
|
|
||||||
penalty += 500
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
"Event": "Nexthop Tracking",
|
|
||||||
}).Debugf("penalty 500 charged: penalty: %d", penalty)
|
|
||||||
|
|
||||||
m.appendPathList(paths)
|
|
||||||
|
|
||||||
isScheduled := m.isScheduled
|
|
||||||
if isScheduled {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
"Event": "Nexthop Tracking",
|
|
||||||
}).Debug("nexthop tracking event already scheduled")
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
m.isScheduled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
delay := m.calculateDelay(penalty)
|
|
||||||
go m.triggerUpdatePathAfter(delay)
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
"Event": "Nexthop Tracking",
|
|
||||||
}).Debugf("nexthop tracking event scheduled in %d secs", delay)
|
|
||||||
|
|
||||||
case <-m.trigger:
|
|
||||||
paths := make(pathList, 0)
|
|
||||||
for _, pList := range m.scheduledPathList {
|
|
||||||
for _, p := range pList {
|
|
||||||
paths = append(paths, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
"Event": "Nexthop Tracking",
|
|
||||||
}).Debugf("update nexthop reachability: %s", paths)
|
|
||||||
|
|
||||||
if err := m.server.UpdatePath("", paths); err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
"Event": "Nexthop Tracking",
|
|
||||||
}).Error("failed to update nexthop reachability")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.isScheduled = false
|
|
||||||
m.scheduledPathList = make(map[string]pathList, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) scheduleUpdate(paths pathList) {
|
|
||||||
if len(paths) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.pathListCh <- paths
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *nexthopTrackingManager) filterPathToRegister(paths pathList) pathList {
|
|
||||||
filteredPaths := make(pathList, 0, len(paths))
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
if path == nil || path.IsFromExternal() {
|
// Here filters out:
|
||||||
|
// - Nil path
|
||||||
|
// - Withdrawn path
|
||||||
|
// - External path (advertised from Zebra) in order avoid sending back
|
||||||
|
// - Unspecified nexthop address
|
||||||
|
// - Already registered nexthop
|
||||||
|
if path == nil || path.IsWithdraw || path.IsFromExternal() {
|
||||||
continue
|
continue
|
||||||
}
|
} else if nexthop := path.GetNexthop(); nexthop.IsUnspecified() {
|
||||||
// NEXTHOP_UNREGISTER message will be sent when GoBGP received
|
|
||||||
// NEXTHOP_UPDATE message and there is no path bound for the updated
|
|
||||||
// nexthop.
|
|
||||||
// Here filters out withdraw paths and paths whose nexthop is:
|
|
||||||
// - already invalidated
|
|
||||||
// - already registered
|
|
||||||
// - unspecified address
|
|
||||||
if path.IsWithdraw || path.IsNexthopInvalid {
|
|
||||||
continue
|
continue
|
||||||
}
|
} else if _, ok := m[nexthop.String()]; ok {
|
||||||
nexthop := path.GetNexthop()
|
|
||||||
if m.isRegisteredNexthop(nexthop) || nexthop.IsUnspecified() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filteredPaths = append(filteredPaths, path)
|
filteredPaths = append(filteredPaths, path)
|
||||||
@ -207,10 +101,14 @@ func (m *nexthopTrackingManager) filterPathToRegister(paths pathList) pathList {
|
|||||||
return filteredPaths
|
return filteredPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterOutExternalPath(paths pathList) pathList {
|
func filterOutExternalPath(paths []*table.Path) []*table.Path {
|
||||||
filteredPaths := make(pathList, 0, len(paths))
|
filteredPaths := make([]*table.Path, 0, len(paths))
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
if path == nil || path.IsFromExternal() {
|
// Here filters out:
|
||||||
|
// - Nil path
|
||||||
|
// - External path (advertised from Zebra) in order avoid sending back
|
||||||
|
// - Unreachable path because invalidated by Zebra
|
||||||
|
if path == nil || path.IsFromExternal() || path.IsNexthopInvalid {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filteredPaths = append(filteredPaths, path)
|
filteredPaths = append(filteredPaths, path)
|
||||||
@ -218,7 +116,7 @@ func filterOutExternalPath(paths pathList) pathList {
|
|||||||
return filteredPaths
|
return filteredPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIPRouteBody(dst pathList) (body *zebra.IPRouteBody, isWithdraw bool) {
|
func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool) {
|
||||||
paths := filterOutExternalPath(dst)
|
paths := filterOutExternalPath(dst)
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -275,24 +173,13 @@ func newIPRouteBody(dst pathList) (body *zebra.IPRouteBody, isWithdraw bool) {
|
|||||||
}, path.IsWithdraw
|
}, path.IsWithdraw
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNexthopRegisterBody(dst pathList, nhtManager *nexthopTrackingManager) (body *zebra.NexthopRegisterBody, isWithdraw bool) {
|
func newNexthopRegisterBody(paths []*table.Path, nexthopCache nexthopStateCache) *zebra.NexthopRegisterBody {
|
||||||
if nhtManager == nil {
|
paths = nexthopCache.filterPathToRegister(paths)
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
paths := nhtManager.filterPathToRegister(dst)
|
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
return nil, false
|
return nil
|
||||||
}
|
}
|
||||||
path := paths[0]
|
path := paths[0]
|
||||||
|
|
||||||
if path.IsWithdraw == true {
|
|
||||||
// NEXTHOP_UNREGISTER message will be sent when GoBGP received
|
|
||||||
// NEXTHOP_UPDATE message and there is no path bound for the updated
|
|
||||||
// nexthop. So there is nothing to do here.
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
family := path.GetRouteFamily()
|
family := path.GetRouteFamily()
|
||||||
nexthops := make([]*zebra.RegisteredNexthop, 0, len(paths))
|
nexthops := make([]*zebra.RegisteredNexthop, 0, len(paths))
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
@ -313,21 +200,29 @@ func newNexthopRegisterBody(dst pathList, nhtManager *nexthopTrackingManager) (b
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nexthops = append(nexthops, nh)
|
nexthops = append(nexthops, nh)
|
||||||
nhtManager.registerNexthop(nexthop)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no nexthop needs to be registered or unregistered,
|
// If no nexthop needs to be registered or unregistered, skips to send
|
||||||
// skips to send message.
|
// message.
|
||||||
if len(nexthops) == 0 {
|
if len(nexthops) == 0 {
|
||||||
return nil, path.IsWithdraw
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &zebra.NexthopRegisterBody{
|
return &zebra.NexthopRegisterBody{
|
||||||
Nexthops: nexthops,
|
Nexthops: nexthops,
|
||||||
}, path.IsWithdraw
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPathFromIPRouteMessage(m *zebra.Message) *table.Path {
|
func newNexthopUnregisterBody(family uint16, prefix net.IP) *zebra.NexthopRegisterBody {
|
||||||
|
return &zebra.NexthopRegisterBody{
|
||||||
|
Nexthops: []*zebra.RegisteredNexthop{{
|
||||||
|
Family: family,
|
||||||
|
Prefix: prefix,
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPathFromIPRouteMessage(m *zebra.Message) *table.Path {
|
||||||
header := m.Header
|
header := m.Header
|
||||||
body := m.Body.(*zebra.IPRouteBody)
|
body := m.Body.(*zebra.IPRouteBody)
|
||||||
family := body.RouteFamily()
|
family := body.RouteFamily()
|
||||||
@ -381,62 +276,52 @@ func createPathFromIPRouteMessage(m *zebra.Message) *table.Path {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func rfListFromNexthopUpdateBody(body *zebra.NexthopUpdateBody) (rfList []bgp.RouteFamily) {
|
type zebraClient struct {
|
||||||
|
client *zebra.Client
|
||||||
|
server *BgpServer
|
||||||
|
nexthopCache nexthopStateCache
|
||||||
|
dead chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *zebraClient) getPathListWithNexthopUpdate(body *zebra.NexthopUpdateBody) []*table.Path {
|
||||||
|
rib := &table.TableManager{
|
||||||
|
Tables: make(map[bgp.RouteFamily]*table.Table),
|
||||||
|
}
|
||||||
|
|
||||||
|
var rfList []bgp.RouteFamily
|
||||||
switch body.Family {
|
switch body.Family {
|
||||||
case uint16(syscall.AF_INET):
|
case uint16(syscall.AF_INET):
|
||||||
return []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN}
|
rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN}
|
||||||
case uint16(syscall.AF_INET6):
|
case uint16(syscall.AF_INET6):
|
||||||
return []bgp.RouteFamily{bgp.RF_IPv6_UC, bgp.RF_IPv6_VPN}
|
rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC, bgp.RF_IPv6_VPN}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createPathListFromNexthopUpdateMessage(body *zebra.NexthopUpdateBody, manager *table.TableManager, nhtManager *nexthopTrackingManager) (pathList, *zebra.NexthopRegisterBody, error) {
|
for _, rf := range rfList {
|
||||||
isNexthopInvalid := len(body.Nexthops) == 0
|
tbl, _, err := z.server.GetRib("", rf, nil)
|
||||||
paths := manager.GetPathListWithNexthop(table.GLOBAL_RIB_NAME, rfListFromNexthopUpdateBody(body), body.Prefix)
|
if err != nil {
|
||||||
pathsLen := len(paths)
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Zebra",
|
||||||
// If there is no path bound for the updated nexthop, send
|
"Family": rf.String(),
|
||||||
// NEXTHOP_UNREGISTER message.
|
"Error": err,
|
||||||
var nexthopUnregisterBody *zebra.NexthopRegisterBody
|
}).Error("failed to get global rib")
|
||||||
if pathsLen == 0 {
|
continue
|
||||||
nexthopUnregisterBody = &zebra.NexthopRegisterBody{
|
|
||||||
Nexthops: []*zebra.RegisteredNexthop{{
|
|
||||||
Family: body.Family,
|
|
||||||
Prefix: body.Prefix,
|
|
||||||
}},
|
|
||||||
}
|
}
|
||||||
nhtManager.unregisterNexthop(body.Prefix)
|
rib.Tables[rf] = tbl
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedPathList := make(pathList, 0, pathsLen)
|
return rib.GetPathListWithNexthop(table.GLOBAL_RIB_NAME, rfList, body.Prefix)
|
||||||
for _, path := range paths {
|
}
|
||||||
newPath := path.Clone(false)
|
|
||||||
if isNexthopInvalid {
|
func (z *zebraClient) updatePathByNexthopCache(paths []*table.Path) {
|
||||||
// If NEXTHOP_UPDATE message does NOT contain any nexthop,
|
paths = z.nexthopCache.applyToPathList(paths)
|
||||||
// invalidates the nexthop reachability.
|
if len(paths) > 0 {
|
||||||
newPath.IsNexthopInvalid = true
|
if err := z.server.UpdatePath("", paths); err != nil {
|
||||||
} else {
|
log.WithFields(log.Fields{
|
||||||
// If NEXTHOP_UPDATE message contains valid nexthops,
|
"Topic": "Zebra",
|
||||||
// copies Metric into MED.
|
"PathList": paths,
|
||||||
newPath.IsNexthopInvalid = false
|
}).Error("failed to update nexthop reachability")
|
||||||
newPath.SetMed(int64(body.Metric), true)
|
|
||||||
}
|
}
|
||||||
updatedPathList = append(updatedPathList, newPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedPathList, nexthopUnregisterBody, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type zebraClient struct {
|
|
||||||
client *zebra.Client
|
|
||||||
server *BgpServer
|
|
||||||
dead chan struct{}
|
|
||||||
nhtManager *nexthopTrackingManager
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *zebraClient) stop() {
|
|
||||||
close(z.dead)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *zebraClient) loop() {
|
func (z *zebraClient) loop() {
|
||||||
@ -446,11 +331,6 @@ func (z *zebraClient) loop() {
|
|||||||
}...)
|
}...)
|
||||||
defer w.Stop()
|
defer w.Stop()
|
||||||
|
|
||||||
if z.nhtManager != nil {
|
|
||||||
go z.nhtManager.loop()
|
|
||||||
defer z.nhtManager.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-z.dead:
|
case <-z.dead:
|
||||||
@ -458,71 +338,69 @@ func (z *zebraClient) loop() {
|
|||||||
case msg := <-z.client.Receive():
|
case msg := <-z.client.Receive():
|
||||||
switch body := msg.Body.(type) {
|
switch body := msg.Body.(type) {
|
||||||
case *zebra.IPRouteBody:
|
case *zebra.IPRouteBody:
|
||||||
if p := createPathFromIPRouteMessage(msg); p != nil {
|
if path := newPathFromIPRouteMessage(msg); path != nil {
|
||||||
if _, err := z.server.AddPath("", pathList{p}); err != nil {
|
if _, err := z.server.AddPath("", []*table.Path{path}); err != nil {
|
||||||
log.Errorf("failed to add path from zebra: %s", p)
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Zebra",
|
||||||
|
"Path": path,
|
||||||
|
"Error": err,
|
||||||
|
}).Error("failed to add path from zebra")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *zebra.NexthopUpdateBody:
|
case *zebra.NexthopUpdateBody:
|
||||||
if z.nhtManager == nil {
|
if updated := z.nexthopCache.updateByNexthopUpdate(body); !updated {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
manager := &table.TableManager{
|
paths := z.getPathListWithNexthopUpdate(body)
|
||||||
Tables: make(map[bgp.RouteFamily]*table.Table),
|
if len(paths) == 0 {
|
||||||
}
|
// If there is no path bound for the given nexthop, send
|
||||||
for _, rf := range rfListFromNexthopUpdateBody(body) {
|
// NEXTHOP_UNREGISTER message.
|
||||||
rib, err := z.server.GetRib("", rf, nil)
|
z.client.SendNexthopRegister(msg.Header.VrfId, newNexthopUnregisterBody(body.Family, body.Prefix), true)
|
||||||
if err != nil {
|
delete(z.nexthopCache, body.Prefix.String())
|
||||||
log.Errorf("failed to get global rib by family %s", rf.String())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
manager.Tables[rf] = rib
|
|
||||||
}
|
|
||||||
if paths, b, err := createPathListFromNexthopUpdateMessage(body, manager, z.nhtManager); err != nil {
|
|
||||||
log.Errorf("failed to create updated path list related to nexthop %s", body.Prefix.String())
|
|
||||||
} else {
|
|
||||||
z.nhtManager.scheduleUpdate(paths)
|
|
||||||
if b != nil {
|
|
||||||
z.client.SendNexthopRegister(msg.Header.VrfId, b, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
z.updatePathByNexthopCache(paths)
|
||||||
}
|
}
|
||||||
case ev := <-w.Event():
|
case ev := <-w.Event():
|
||||||
switch msg := ev.(type) {
|
switch msg := ev.(type) {
|
||||||
case *WatchEventBestPath:
|
case *WatchEventBestPath:
|
||||||
if table.UseMultiplePaths.Enabled {
|
if table.UseMultiplePaths.Enabled {
|
||||||
for _, dst := range msg.MultiPathList {
|
for _, paths := range msg.MultiPathList {
|
||||||
if body, isWithdraw := newIPRouteBody(dst); body != nil {
|
z.updatePathByNexthopCache(paths)
|
||||||
|
if body, isWithdraw := newIPRouteBody(paths); body != nil {
|
||||||
z.client.SendIPRoute(0, body, isWithdraw)
|
z.client.SendIPRoute(0, body, isWithdraw)
|
||||||
}
|
}
|
||||||
if body, isWithdraw := newNexthopRegisterBody(dst, z.nhtManager); body != nil {
|
if body := newNexthopRegisterBody(paths, z.nexthopCache); body != nil {
|
||||||
z.client.SendNexthopRegister(0, body, isWithdraw)
|
z.client.SendNexthopRegister(0, body, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
z.updatePathByNexthopCache(msg.PathList)
|
||||||
for _, path := range msg.PathList {
|
for _, path := range msg.PathList {
|
||||||
if len(path.VrfIds) == 0 {
|
vrfs := []uint16{0}
|
||||||
path.VrfIds = []uint16{0}
|
if msg.Vrf != nil {
|
||||||
|
if v, ok := msg.Vrf[path.GetNlri().String()]; ok {
|
||||||
|
vrfs = append(vrfs, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, i := range path.VrfIds {
|
for _, i := range vrfs {
|
||||||
if body, isWithdraw := newIPRouteBody(pathList{path}); body != nil {
|
if body, isWithdraw := newIPRouteBody([]*table.Path{path}); body != nil {
|
||||||
z.client.SendIPRoute(i, body, isWithdraw)
|
z.client.SendIPRoute(i, body, isWithdraw)
|
||||||
}
|
}
|
||||||
if body, isWithdraw := newNexthopRegisterBody(pathList{path}, z.nhtManager); body != nil {
|
if body := newNexthopRegisterBody([]*table.Path{path}, z.nexthopCache); body != nil {
|
||||||
z.client.SendNexthopRegister(i, body, isWithdraw)
|
z.client.SendNexthopRegister(i, body, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *WatchEventUpdate:
|
case *WatchEventUpdate:
|
||||||
if body, isWithdraw := newNexthopRegisterBody(msg.PathList, z.nhtManager); body != nil {
|
if body := newNexthopRegisterBody(msg.PathList, z.nexthopCache); body != nil {
|
||||||
vrfId := uint16(0)
|
vrfID := uint16(0)
|
||||||
for _, vrf := range z.server.GetVrf() {
|
for _, vrf := range z.server.GetVrf() {
|
||||||
if vrf.Name == msg.Neighbor.Config.Vrf {
|
if vrf.Name == msg.Neighbor.Config.Vrf {
|
||||||
vrfId = uint16(vrf.Id)
|
vrfID = uint16(vrf.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
z.client.SendNexthopRegister(vrfId, body, isWithdraw)
|
z.client.SendNexthopRegister(vrfID, body, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -561,15 +439,11 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh
|
|||||||
}
|
}
|
||||||
cli.SendRedistribute(t, zebra.VRF_DEFAULT)
|
cli.SendRedistribute(t, zebra.VRF_DEFAULT)
|
||||||
}
|
}
|
||||||
var nhtManager *nexthopTrackingManager = nil
|
|
||||||
if nhtEnable {
|
|
||||||
nhtManager = newNexthopTrackingManager(s, int(nhtDelay))
|
|
||||||
}
|
|
||||||
w := &zebraClient{
|
w := &zebraClient{
|
||||||
dead: make(chan struct{}),
|
client: cli,
|
||||||
client: cli,
|
server: s,
|
||||||
server: s,
|
nexthopCache: make(nexthopStateCache),
|
||||||
nhtManager: nhtManager,
|
dead: make(chan struct{}),
|
||||||
}
|
}
|
||||||
go w.loop()
|
go w.loop()
|
||||||
return w, nil
|
return w, nil
|
||||||
|
|||||||
83
vendor/github.com/osrg/gobgp/table/adj.go
generated
vendored
83
vendor/github.com/osrg/gobgp/table/adj.go
generated
vendored
@ -22,18 +22,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AdjRib struct {
|
type AdjRib struct {
|
||||||
id string
|
|
||||||
accepted map[bgp.RouteFamily]int
|
accepted map[bgp.RouteFamily]int
|
||||||
table map[bgp.RouteFamily]map[string]*Path
|
table map[bgp.RouteFamily]map[string]*Path
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAdjRib(id string, rfList []bgp.RouteFamily) *AdjRib {
|
func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
|
||||||
table := make(map[bgp.RouteFamily]map[string]*Path)
|
table := make(map[bgp.RouteFamily]map[string]*Path)
|
||||||
for _, rf := range rfList {
|
for _, rf := range rfList {
|
||||||
table[rf] = make(map[string]*Path)
|
table[rf] = make(map[string]*Path)
|
||||||
}
|
}
|
||||||
return &AdjRib{
|
return &AdjRib{
|
||||||
id: id,
|
|
||||||
table: table,
|
table: table,
|
||||||
accepted: make(map[bgp.RouteFamily]int),
|
accepted: make(map[bgp.RouteFamily]int),
|
||||||
}
|
}
|
||||||
@ -51,21 +49,19 @@ func (adj *AdjRib) Update(pathList []*Path) {
|
|||||||
if path.IsWithdraw {
|
if path.IsWithdraw {
|
||||||
if found {
|
if found {
|
||||||
delete(adj.table[rf], key)
|
delete(adj.table[rf], key)
|
||||||
if old.Filtered(adj.id) != POLICY_DIRECTION_IN {
|
if !old.IsAsLooped() {
|
||||||
adj.accepted[rf]--
|
adj.accepted[rf]--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n := path.Filtered(adj.id)
|
|
||||||
if found {
|
if found {
|
||||||
o := old.Filtered(adj.id)
|
if old.IsAsLooped() && !path.IsAsLooped() {
|
||||||
if o == POLICY_DIRECTION_IN && n == POLICY_DIRECTION_NONE {
|
|
||||||
adj.accepted[rf]++
|
adj.accepted[rf]++
|
||||||
} else if o != POLICY_DIRECTION_IN && n == POLICY_DIRECTION_IN {
|
} else if !old.IsAsLooped() && path.IsAsLooped() {
|
||||||
adj.accepted[rf]--
|
adj.accepted[rf]--
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if n == POLICY_DIRECTION_NONE {
|
if !path.IsAsLooped() {
|
||||||
adj.accepted[rf]++
|
adj.accepted[rf]++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,22 +73,11 @@ func (adj *AdjRib) Update(pathList []*Path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adj *AdjRib) RefreshAcceptedNumber(rfList []bgp.RouteFamily) {
|
|
||||||
for _, rf := range rfList {
|
|
||||||
adj.accepted[rf] = 0
|
|
||||||
for _, p := range adj.table[rf] {
|
|
||||||
if p.Filtered(adj.id) != POLICY_DIRECTION_IN {
|
|
||||||
adj.accepted[rf]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
|
func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
|
||||||
pathList := make([]*Path, 0, adj.Count(rfList))
|
pathList := make([]*Path, 0, adj.Count(rfList))
|
||||||
for _, rf := range rfList {
|
for _, rf := range rfList {
|
||||||
for _, rr := range adj.table[rf] {
|
for _, rr := range adj.table[rf] {
|
||||||
if accepted && rr.Filtered(adj.id) == POLICY_DIRECTION_IN {
|
if accepted && rr.IsAsLooped() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
pathList = append(pathList, rr)
|
pathList = append(pathList, rr)
|
||||||
@ -134,10 +119,10 @@ func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
|
|||||||
pathList := make([]*Path, 0, adj.Count(rfList))
|
pathList := make([]*Path, 0, adj.Count(rfList))
|
||||||
for _, rf := range rfList {
|
for _, rf := range rfList {
|
||||||
if table, ok := adj.table[rf]; ok {
|
if table, ok := adj.table[rf]; ok {
|
||||||
for _, p := range table {
|
for k, p := range table {
|
||||||
if p.IsStale() {
|
if p.IsStale() {
|
||||||
delete(table, p.getPrefix())
|
delete(table, k)
|
||||||
if p.Filtered(adj.id) == POLICY_DIRECTION_NONE {
|
if !p.IsAsLooped() {
|
||||||
adj.accepted[rf]--
|
adj.accepted[rf]--
|
||||||
}
|
}
|
||||||
pathList = append(pathList, p.Clone(true))
|
pathList = append(pathList, p.Clone(true))
|
||||||
@ -148,45 +133,41 @@ func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
|
|||||||
return pathList
|
return pathList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) {
|
func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
|
||||||
|
pathList := make([]*Path, 0)
|
||||||
for _, rf := range rfList {
|
for _, rf := range rfList {
|
||||||
if table, ok := adj.table[rf]; ok {
|
if table, ok := adj.table[rf]; ok {
|
||||||
for _, p := range table {
|
l := make([]*Path, 0, len(table))
|
||||||
p.MarkStale(true)
|
for k, p := range table {
|
||||||
|
n := p.Clone(false)
|
||||||
|
n.MarkStale(true)
|
||||||
|
table[k] = n
|
||||||
|
l = append(l, n)
|
||||||
|
}
|
||||||
|
if len(l) > 0 {
|
||||||
|
pathList = append(pathList, l...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return pathList
|
||||||
|
|
||||||
func (adj *AdjRib) Exists(path *Path) bool {
|
|
||||||
if path == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
family := path.GetRouteFamily()
|
|
||||||
table, ok := adj.table[family]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, ok = table[path.getPrefix()]
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
|
func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
|
||||||
paths := adj.PathList([]bgp.RouteFamily{family}, accepted)
|
m := make(map[string][]*Path)
|
||||||
dsts := make(map[string]*Destination, len(paths))
|
pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
|
||||||
for _, path := range paths {
|
for _, path := range pl {
|
||||||
if d, y := dsts[path.GetNlri().String()]; y {
|
key := path.GetNlri().String()
|
||||||
d.knownPathList = append(d.knownPathList, path)
|
if _, y := m[key]; y {
|
||||||
|
m[key] = append(m[key], path)
|
||||||
} else {
|
} else {
|
||||||
dst := NewDestination(path.GetNlri(), 0)
|
m[key] = []*Path{path}
|
||||||
dsts[path.GetNlri().String()] = dst
|
|
||||||
dst.knownPathList = append(dst.knownPathList, path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbl := &Table{
|
d := make([]*Destination, 0, len(pl))
|
||||||
routeFamily: family,
|
for _, l := range m {
|
||||||
destinations: dsts,
|
d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
|
||||||
}
|
}
|
||||||
|
tbl := NewTable(family, d...)
|
||||||
option = append(option, TableSelectOption{adj: true})
|
option = append(option, TableSelectOption{adj: true})
|
||||||
return tbl.Select(option...)
|
return tbl.Select(option...)
|
||||||
}
|
}
|
||||||
|
|||||||
749
vendor/github.com/osrg/gobgp/table/destination.go
generated
vendored
749
vendor/github.com/osrg/gobgp/table/destination.go
generated
vendored
@ -150,7 +150,7 @@ func (i *PeerInfo) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo {
|
func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo {
|
||||||
id := net.ParseIP(string(p.RouteReflector.Config.RouteReflectorClusterId)).To4()
|
clusterID := net.ParseIP(string(p.RouteReflector.State.RouteReflectorClusterId)).To4()
|
||||||
// exclude zone info
|
// exclude zone info
|
||||||
naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress)
|
naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress)
|
||||||
return &PeerInfo{
|
return &PeerInfo{
|
||||||
@ -159,21 +159,17 @@ func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo {
|
|||||||
LocalID: net.ParseIP(g.Config.RouterId).To4(),
|
LocalID: net.ParseIP(g.Config.RouterId).To4(),
|
||||||
RouteReflectorClient: p.RouteReflector.Config.RouteReflectorClient,
|
RouteReflectorClient: p.RouteReflector.Config.RouteReflectorClient,
|
||||||
Address: naddr.IP,
|
Address: naddr.IP,
|
||||||
RouteReflectorClusterID: id,
|
RouteReflectorClusterID: clusterID,
|
||||||
MultihopTtl: p.EbgpMultihop.Config.MultihopTtl,
|
MultihopTtl: p.EbgpMultihop.Config.MultihopTtl,
|
||||||
Confederation: p.IsConfederationMember(g),
|
Confederation: p.IsConfederationMember(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Destination struct {
|
type Destination struct {
|
||||||
routeFamily bgp.RouteFamily
|
routeFamily bgp.RouteFamily
|
||||||
nlri bgp.AddrPrefixInterface
|
nlri bgp.AddrPrefixInterface
|
||||||
knownPathList paths
|
knownPathList []*Path
|
||||||
withdrawList paths
|
localIdMap *Bitmap
|
||||||
newPathList paths
|
|
||||||
oldKnownPathList paths
|
|
||||||
RadixKey string
|
|
||||||
localIdMap *Bitmap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDestination(nlri bgp.AddrPrefixInterface, mapSize int, known ...*Path) *Destination {
|
func NewDestination(nlri bgp.AddrPrefixInterface, mapSize int, known ...*Path) *Destination {
|
||||||
@ -181,18 +177,12 @@ func NewDestination(nlri bgp.AddrPrefixInterface, mapSize int, known ...*Path) *
|
|||||||
routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()),
|
routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()),
|
||||||
nlri: nlri,
|
nlri: nlri,
|
||||||
knownPathList: known,
|
knownPathList: known,
|
||||||
withdrawList: make([]*Path, 0),
|
|
||||||
newPathList: make([]*Path, 0),
|
|
||||||
localIdMap: NewBitmap(mapSize),
|
localIdMap: NewBitmap(mapSize),
|
||||||
}
|
}
|
||||||
// the id zero means id is not allocated yet.
|
// the id zero means id is not allocated yet.
|
||||||
if mapSize != 0 {
|
if mapSize != 0 {
|
||||||
d.localIdMap.Flag(0)
|
d.localIdMap.Flag(0)
|
||||||
}
|
}
|
||||||
switch d.routeFamily {
|
|
||||||
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS:
|
|
||||||
d.RadixKey = AddrToRadixkey(nlri)
|
|
||||||
}
|
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,34 +206,332 @@ func (dd *Destination) GetAllKnownPathList() []*Path {
|
|||||||
return dd.knownPathList
|
return dd.knownPathList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dd *Destination) GetKnownPathList(id string) []*Path {
|
func rsFilter(id string, as uint32, path *Path) bool {
|
||||||
|
isASLoop := func(as uint32, path *Path) bool {
|
||||||
|
for _, v := range path.GetAsList() {
|
||||||
|
if as == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if id != GLOBAL_RIB_NAME && (path.GetSource().Address.String() == id || isASLoop(as, path)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dd *Destination) GetKnownPathList(id string, as uint32) []*Path {
|
||||||
list := make([]*Path, 0, len(dd.knownPathList))
|
list := make([]*Path, 0, len(dd.knownPathList))
|
||||||
for _, p := range dd.knownPathList {
|
for _, p := range dd.knownPathList {
|
||||||
if p.Filtered(id) == POLICY_DIRECTION_NONE {
|
if rsFilter(id, as, p) {
|
||||||
list = append(list, p)
|
continue
|
||||||
}
|
}
|
||||||
|
list = append(list, p)
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBestPath(id string, pathList *paths) *Path {
|
func getBestPath(id string, as uint32, pathList []*Path) *Path {
|
||||||
for _, p := range *pathList {
|
for _, p := range pathList {
|
||||||
if p.Filtered(id) == POLICY_DIRECTION_NONE && !p.IsNexthopInvalid {
|
if rsFilter(id, as, p) {
|
||||||
return p
|
continue
|
||||||
}
|
}
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dd *Destination) GetBestPath(id string) *Path {
|
func (dd *Destination) GetBestPath(id string, as uint32) *Path {
|
||||||
return getBestPath(id, &dd.knownPathList)
|
p := getBestPath(id, as, dd.knownPathList)
|
||||||
|
if p == nil || p.IsNexthopInvalid {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMultiBestPath(id string, pathList *paths) []*Path {
|
func (dd *Destination) GetMultiBestPath(id string) []*Path {
|
||||||
list := make([]*Path, 0, len(*pathList))
|
return getMultiBestPath(id, dd.knownPathList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates best-path among known paths for this destination.
|
||||||
|
//
|
||||||
|
// Modifies destination's state related to stored paths. Removes withdrawn
|
||||||
|
// paths from known paths. Also, adds new paths to known paths.
|
||||||
|
func (dest *Destination) Calculate(newPath *Path) *Update {
|
||||||
|
oldKnownPathList := make([]*Path, len(dest.knownPathList))
|
||||||
|
copy(oldKnownPathList, dest.knownPathList)
|
||||||
|
|
||||||
|
if newPath.IsWithdraw {
|
||||||
|
p := dest.explicitWithdraw(newPath)
|
||||||
|
if p != nil {
|
||||||
|
if id := p.GetNlri().PathLocalIdentifier(); id != 0 {
|
||||||
|
dest.localIdMap.Unflag(uint(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest.implicitWithdraw(newPath)
|
||||||
|
dest.knownPathList = append(dest.knownPathList, newPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range dest.knownPathList {
|
||||||
|
if path.GetNlri().PathLocalIdentifier() == 0 {
|
||||||
|
id, err := dest.localIdMap.FindandSetZeroBit()
|
||||||
|
if err != nil {
|
||||||
|
dest.localIdMap.Expand()
|
||||||
|
id, _ = dest.localIdMap.FindandSetZeroBit()
|
||||||
|
}
|
||||||
|
path.GetNlri().SetPathLocalIdentifier(uint32(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compute new best path
|
||||||
|
dest.computeKnownBestPath()
|
||||||
|
|
||||||
|
l := make([]*Path, len(dest.knownPathList))
|
||||||
|
copy(l, dest.knownPathList)
|
||||||
|
return &Update{
|
||||||
|
KnownPathList: l,
|
||||||
|
OldKnownPathList: oldKnownPathList,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes withdrawn paths.
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// We may have disproportionate number of withdraws compared to know paths
|
||||||
|
// since not all paths get installed into the table due to bgp policy and
|
||||||
|
// we can receive withdraws for such paths and withdrawals may not be
|
||||||
|
// stopped by the same policies.
|
||||||
|
//
|
||||||
|
func (dest *Destination) explicitWithdraw(withdraw *Path) *Path {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
"Key": dest.GetNlri().String(),
|
||||||
|
}).Debug("Removing withdrawals")
|
||||||
|
|
||||||
|
// If we have some withdrawals and no know-paths, it means it is safe to
|
||||||
|
// delete these withdraws.
|
||||||
|
if len(dest.knownPathList) == 0 {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
"Key": dest.GetNlri().String(),
|
||||||
|
}).Debug("Found withdrawals for path(s) that did not get installed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match all withdrawals from destination paths.
|
||||||
|
isFound := -1
|
||||||
|
for i, path := range dest.knownPathList {
|
||||||
|
// We have a match if the source and path-id are same.
|
||||||
|
if path.GetSource().Equal(withdraw.GetSource()) && path.GetNlri().PathIdentifier() == withdraw.GetNlri().PathIdentifier() {
|
||||||
|
isFound = i
|
||||||
|
withdraw.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do no have any match for this withdraw.
|
||||||
|
if isFound == -1 {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
"Key": dest.GetNlri().String(),
|
||||||
|
"Path": withdraw,
|
||||||
|
}).Warn("No matching path for withdraw found, may be path was not installed into table")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
p := dest.knownPathList[isFound]
|
||||||
|
dest.knownPathList = append(dest.knownPathList[:isFound], dest.knownPathList[isFound+1:]...)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifies which of known paths are old and removes them.
|
||||||
|
//
|
||||||
|
// Known paths will no longer have paths whose new version is present in
|
||||||
|
// new paths.
|
||||||
|
func (dest *Destination) implicitWithdraw(newPath *Path) {
|
||||||
|
found := -1
|
||||||
|
for i, path := range dest.knownPathList {
|
||||||
|
if newPath.NoImplicitWithdraw() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Here we just check if source is same and not check if path
|
||||||
|
// version num. as newPaths are implicit withdrawal of old
|
||||||
|
// paths and when doing RouteRefresh (not EnhancedRouteRefresh)
|
||||||
|
// we get same paths again.
|
||||||
|
if newPath.GetSource().Equal(path.GetSource()) && newPath.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
"Key": dest.GetNlri().String(),
|
||||||
|
"Path": path,
|
||||||
|
}).Debug("Implicit withdrawal of old path, since we have learned new path from the same peer")
|
||||||
|
|
||||||
|
found = i
|
||||||
|
newPath.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found != -1 {
|
||||||
|
dest.knownPathList = append(dest.knownPathList[:found], dest.knownPathList[found+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dest *Destination) computeKnownBestPath() (*Path, BestPathReason, error) {
|
||||||
|
if SelectionOptions.DisableBestPathSelection {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
}).Debug("computeKnownBestPath skipped")
|
||||||
|
return nil, BPR_DISABLED, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we do not have any paths to this destination, then we do not have
|
||||||
|
// new best path.
|
||||||
|
if len(dest.knownPathList) == 0 {
|
||||||
|
return nil, BPR_UNKNOWN, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
}).Debugf("computeKnownBestPath knownPathList: %d", len(dest.knownPathList))
|
||||||
|
|
||||||
|
// We pick the first path as current best path. This helps in breaking
|
||||||
|
// tie between two new paths learned in one cycle for which best-path
|
||||||
|
// calculation steps lead to tie.
|
||||||
|
if len(dest.knownPathList) == 1 {
|
||||||
|
// If the first path has the invalidated next-hop, which evaluated by
|
||||||
|
// IGP, returns no path with the reason of the next-hop reachability.
|
||||||
|
if dest.knownPathList[0].IsNexthopInvalid {
|
||||||
|
return nil, BPR_REACHABLE_NEXT_HOP, nil
|
||||||
|
}
|
||||||
|
return dest.knownPathList[0], BPR_ONLY_PATH, nil
|
||||||
|
}
|
||||||
|
dest.sort()
|
||||||
|
newBest := dest.knownPathList[0]
|
||||||
|
// If the first path has the invalidated next-hop, which evaluated by IGP,
|
||||||
|
// returns no path with the reason of the next-hop reachability.
|
||||||
|
if dest.knownPathList[0].IsNexthopInvalid {
|
||||||
|
return nil, BPR_REACHABLE_NEXT_HOP, nil
|
||||||
|
}
|
||||||
|
return newBest, newBest.reason, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *Destination) sort() {
|
||||||
|
sort.SliceStable(dst.knownPathList, func(i, j int) bool {
|
||||||
|
//Compares given paths and returns best path.
|
||||||
|
//
|
||||||
|
//Parameters:
|
||||||
|
// -`path1`: first path to compare
|
||||||
|
// -`path2`: second path to compare
|
||||||
|
//
|
||||||
|
// Best path processing will involve following steps:
|
||||||
|
// 1. Select a path with a reachable next hop.
|
||||||
|
// 2. Select the path with the highest weight.
|
||||||
|
// 3. If path weights are the same, select the path with the highest
|
||||||
|
// local preference value.
|
||||||
|
// 4. Prefer locally originated routes (network routes, redistributed
|
||||||
|
// routes, or aggregated routes) over received routes.
|
||||||
|
// 5. Select the route with the shortest AS-path length.
|
||||||
|
// 6. If all paths have the same AS-path length, select the path based
|
||||||
|
// on origin: IGP is preferred over EGP; EGP is preferred over
|
||||||
|
// Incomplete.
|
||||||
|
// 7. If the origins are the same, select the path with lowest MED
|
||||||
|
// value.
|
||||||
|
// 8. If the paths have the same MED values, select the path learned
|
||||||
|
// via EBGP over one learned via IBGP.
|
||||||
|
// 9. Select the route with the lowest IGP cost to the next hop.
|
||||||
|
// 10. Select the route received from the peer with the lowest BGP
|
||||||
|
// router ID.
|
||||||
|
//
|
||||||
|
// Returns None if best-path among given paths cannot be computed else best
|
||||||
|
// path.
|
||||||
|
// Assumes paths from NC has source equal to None.
|
||||||
|
//
|
||||||
|
|
||||||
|
path1 := dst.knownPathList[i]
|
||||||
|
path2 := dst.knownPathList[j]
|
||||||
|
|
||||||
|
var better *Path
|
||||||
|
reason := BPR_UNKNOWN
|
||||||
|
|
||||||
|
// draft-uttaro-idr-bgp-persistence-02
|
||||||
|
if better == nil {
|
||||||
|
better = compareByLLGRStaleCommunity(path1, path2)
|
||||||
|
reason = BPR_NON_LLGR_STALE
|
||||||
|
}
|
||||||
|
// Follow best path calculation algorithm steps.
|
||||||
|
// compare by reachability
|
||||||
|
if better == nil {
|
||||||
|
better = compareByReachableNexthop(path1, path2)
|
||||||
|
reason = BPR_REACHABLE_NEXT_HOP
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByHighestWeight(path1, path2)
|
||||||
|
reason = BPR_HIGHEST_WEIGHT
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByLocalPref(path1, path2)
|
||||||
|
reason = BPR_LOCAL_PREF
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByLocalOrigin(path1, path2)
|
||||||
|
reason = BPR_LOCAL_ORIGIN
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByASPath(path1, path2)
|
||||||
|
reason = BPR_ASPATH
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByOrigin(path1, path2)
|
||||||
|
reason = BPR_ORIGIN
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByMED(path1, path2)
|
||||||
|
reason = BPR_MED
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByASNumber(path1, path2)
|
||||||
|
reason = BPR_ASN
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByIGPCost(path1, path2)
|
||||||
|
reason = BPR_IGP_COST
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
better = compareByAge(path1, path2)
|
||||||
|
reason = BPR_OLDER
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
var e error = nil
|
||||||
|
better, e = compareByRouterID(path1, path2)
|
||||||
|
if e != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Table",
|
||||||
|
"Error": e,
|
||||||
|
}).Error("Could not get best path by comparing router ID")
|
||||||
|
}
|
||||||
|
reason = BPR_ROUTER_ID
|
||||||
|
}
|
||||||
|
if better == nil {
|
||||||
|
reason = BPR_UNKNOWN
|
||||||
|
better = path1
|
||||||
|
}
|
||||||
|
|
||||||
|
better.reason = reason
|
||||||
|
|
||||||
|
return better == path1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Update struct {
|
||||||
|
KnownPathList []*Path
|
||||||
|
OldKnownPathList []*Path
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMultiBestPath(id string, pathList []*Path) []*Path {
|
||||||
|
list := make([]*Path, 0, len(pathList))
|
||||||
var best *Path
|
var best *Path
|
||||||
for _, p := range *pathList {
|
for _, p := range pathList {
|
||||||
if p.Filtered(id) == POLICY_DIRECTION_NONE && !p.IsNexthopInvalid {
|
if !p.IsNexthopInvalid {
|
||||||
if best == nil {
|
if best == nil {
|
||||||
best = p
|
best = p
|
||||||
list = append(list, p)
|
list = append(list, p)
|
||||||
@ -255,25 +543,33 @@ func getMultiBestPath(id string, pathList *paths) []*Path {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dd *Destination) GetMultiBestPath(id string) []*Path {
|
func (u *Update) GetWithdrawnPath() []*Path {
|
||||||
return getMultiBestPath(id, &dd.knownPathList)
|
if len(u.KnownPathList) == len(u.OldKnownPathList) {
|
||||||
}
|
return nil
|
||||||
|
|
||||||
func (dd *Destination) GetAddPathChanges(id string) []*Path {
|
|
||||||
l := make([]*Path, 0, len(dd.newPathList)+len(dd.withdrawList))
|
|
||||||
for _, p := range dd.newPathList {
|
|
||||||
l = append(l, p)
|
|
||||||
}
|
}
|
||||||
for _, p := range dd.withdrawList {
|
|
||||||
l = append(l, p.Clone(true))
|
l := make([]*Path, 0, len(u.OldKnownPathList))
|
||||||
|
|
||||||
|
for _, p := range u.OldKnownPathList {
|
||||||
|
y := func() bool {
|
||||||
|
for _, old := range u.KnownPathList {
|
||||||
|
if p == old {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}()
|
||||||
|
if !y {
|
||||||
|
l = append(l, p.Clone(true))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dd *Destination) GetChanges(id string, peerDown bool) (*Path, *Path, []*Path) {
|
func (u *Update) GetChanges(id string, as uint32, peerDown bool) (*Path, *Path, []*Path) {
|
||||||
best, old := func(id string) (*Path, *Path) {
|
best, old := func(id string) (*Path, *Path) {
|
||||||
old := getBestPath(id, &dd.oldKnownPathList)
|
old := getBestPath(id, as, u.OldKnownPathList)
|
||||||
best := dd.GetBestPath(id)
|
best := getBestPath(id, as, u.KnownPathList)
|
||||||
if best != nil && best.Equal(old) {
|
if best != nil && best.Equal(old) {
|
||||||
// RFC4684 3.2. Intra-AS VPN Route Distribution
|
// RFC4684 3.2. Intra-AS VPN Route Distribution
|
||||||
// When processing RT membership NLRIs received from internal iBGP
|
// When processing RT membership NLRIs received from internal iBGP
|
||||||
@ -286,6 +582,11 @@ func (dd *Destination) GetChanges(id string, peerDown bool) (*Path, *Path, []*Pa
|
|||||||
// For BGP Nexthop Tracking, checks if the nexthop reachability
|
// For BGP Nexthop Tracking, checks if the nexthop reachability
|
||||||
// was changed or not.
|
// was changed or not.
|
||||||
if best.IsNexthopInvalid != old.IsNexthopInvalid {
|
if best.IsNexthopInvalid != old.IsNexthopInvalid {
|
||||||
|
// If the nexthop of the best path became unreachable, we need
|
||||||
|
// to withdraw that path.
|
||||||
|
if best.IsNexthopInvalid {
|
||||||
|
return best.Clone(true), old
|
||||||
|
}
|
||||||
return best, old
|
return best, old
|
||||||
}
|
}
|
||||||
return nil, old
|
return nil, old
|
||||||
@ -320,8 +621,8 @@ func (dd *Destination) GetChanges(id string, peerDown bool) (*Path, *Path, []*Pa
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
oldM := getMultiBestPath(id, &dd.oldKnownPathList)
|
oldM := getMultiBestPath(id, u.OldKnownPathList)
|
||||||
newM := dd.GetMultiBestPath(id)
|
newM := getMultiBestPath(id, u.KnownPathList)
|
||||||
if diff(oldM, newM) {
|
if diff(oldM, newM) {
|
||||||
multi = newM
|
multi = newM
|
||||||
if len(newM) == 0 {
|
if len(newM) == 0 {
|
||||||
@ -332,348 +633,6 @@ func (dd *Destination) GetChanges(id string, peerDown bool) (*Path, *Path, []*Pa
|
|||||||
return best, old, multi
|
return best, old, multi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dd *Destination) AddWithdraw(withdraw *Path) {
|
|
||||||
dd.validatePath(withdraw)
|
|
||||||
dd.withdrawList = append(dd.withdrawList, withdraw)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dd *Destination) AddNewPath(newPath *Path) {
|
|
||||||
dd.validatePath(newPath)
|
|
||||||
dd.newPathList = append(dd.newPathList, newPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dd *Destination) validatePath(path *Path) {
|
|
||||||
if path == nil || path.GetRouteFamily() != dd.routeFamily {
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Key": dd.GetNlri().String(),
|
|
||||||
"Path": path,
|
|
||||||
"ExpectedRF": dd.routeFamily,
|
|
||||||
}).Error("path is nil or invalid route family")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculates best-path among known paths for this destination.
|
|
||||||
//
|
|
||||||
// Modifies destination's state related to stored paths. Removes withdrawn
|
|
||||||
// paths from known paths. Also, adds new paths to known paths.
|
|
||||||
func (dest *Destination) Calculate() *Destination {
|
|
||||||
oldKnownPathList := dest.knownPathList
|
|
||||||
newPathList := dest.newPathList
|
|
||||||
// First remove the withdrawn paths.
|
|
||||||
withdrawn := dest.explicitWithdraw()
|
|
||||||
// Do implicit withdrawal
|
|
||||||
dest.implicitWithdraw()
|
|
||||||
|
|
||||||
for _, path := range withdrawn {
|
|
||||||
if id := path.GetNlri().PathLocalIdentifier(); id != 0 {
|
|
||||||
dest.localIdMap.Unflag(uint(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Collect all new paths into known paths.
|
|
||||||
dest.knownPathList = append(dest.knownPathList, dest.newPathList...)
|
|
||||||
|
|
||||||
for _, path := range dest.knownPathList {
|
|
||||||
if path.GetNlri().PathLocalIdentifier() == 0 {
|
|
||||||
id, err := dest.localIdMap.FindandSetZeroBit()
|
|
||||||
if err != nil {
|
|
||||||
dest.localIdMap.Expand()
|
|
||||||
id, _ = dest.localIdMap.FindandSetZeroBit()
|
|
||||||
}
|
|
||||||
path.GetNlri().SetPathLocalIdentifier(uint32(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Clear new paths as we copied them.
|
|
||||||
dest.newPathList = make([]*Path, 0)
|
|
||||||
// Compute new best path
|
|
||||||
dest.computeKnownBestPath()
|
|
||||||
|
|
||||||
return &Destination{
|
|
||||||
routeFamily: dest.routeFamily,
|
|
||||||
nlri: dest.nlri,
|
|
||||||
knownPathList: dest.knownPathList,
|
|
||||||
oldKnownPathList: oldKnownPathList,
|
|
||||||
newPathList: newPathList,
|
|
||||||
withdrawList: withdrawn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes withdrawn paths.
|
|
||||||
//
|
|
||||||
// Note:
|
|
||||||
// We may have disproportionate number of withdraws compared to know paths
|
|
||||||
// since not all paths get installed into the table due to bgp policy and
|
|
||||||
// we can receive withdraws for such paths and withdrawals may not be
|
|
||||||
// stopped by the same policies.
|
|
||||||
//
|
|
||||||
func (dest *Destination) explicitWithdraw() paths {
|
|
||||||
|
|
||||||
// If we have no withdrawals, we have nothing to do.
|
|
||||||
if len(dest.withdrawList) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Key": dest.GetNlri().String(),
|
|
||||||
"Length": len(dest.withdrawList),
|
|
||||||
}).Debug("Removing withdrawals")
|
|
||||||
|
|
||||||
// If we have some withdrawals and no know-paths, it means it is safe to
|
|
||||||
// delete these withdraws.
|
|
||||||
if len(dest.knownPathList) == 0 {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Key": dest.GetNlri().String(),
|
|
||||||
"Length": len(dest.withdrawList),
|
|
||||||
}).Debug("Found withdrawals for path(s) that did not get installed")
|
|
||||||
dest.withdrawList = []*Path{}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have some known paths and some withdrawals, we find matches and
|
|
||||||
// delete them first.
|
|
||||||
matches := make([]*Path, 0, len(dest.withdrawList)/2)
|
|
||||||
newKnownPaths := make([]*Path, 0, len(dest.knownPathList)/2)
|
|
||||||
|
|
||||||
// Match all withdrawals from destination paths.
|
|
||||||
for _, withdraw := range dest.withdrawList {
|
|
||||||
isFound := false
|
|
||||||
for _, path := range dest.knownPathList {
|
|
||||||
// We have a match if the source and path-id are same.
|
|
||||||
if path.GetSource().Equal(withdraw.GetSource()) && path.GetNlri().PathIdentifier() == withdraw.GetNlri().PathIdentifier() {
|
|
||||||
isFound = true
|
|
||||||
// this path is referenced in peer's adj-rib-in
|
|
||||||
// when there was no policy modification applied.
|
|
||||||
// we could flag IsWithdraw down after use to avoid
|
|
||||||
// a path with IsWithdraw flag exists in adj-rib-in
|
|
||||||
path.IsWithdraw = true
|
|
||||||
withdraw.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
|
|
||||||
matches = append(matches, withdraw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do no have any match for this withdraw.
|
|
||||||
if !isFound {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Key": dest.GetNlri().String(),
|
|
||||||
"Path": withdraw,
|
|
||||||
}).Warn("No matching path for withdraw found, may be path was not installed into table")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, path := range dest.knownPathList {
|
|
||||||
if !path.IsWithdraw {
|
|
||||||
newKnownPaths = append(newKnownPaths, path)
|
|
||||||
}
|
|
||||||
// here we flag IsWithdraw down
|
|
||||||
path.IsWithdraw = false
|
|
||||||
}
|
|
||||||
|
|
||||||
dest.knownPathList = newKnownPaths
|
|
||||||
dest.withdrawList = make([]*Path, 0)
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identifies which of known paths are old and removes them.
|
|
||||||
//
|
|
||||||
// Known paths will no longer have paths whose new version is present in
|
|
||||||
// new paths.
|
|
||||||
func (dest *Destination) implicitWithdraw() paths {
|
|
||||||
newKnownPaths := make([]*Path, 0, len(dest.knownPathList))
|
|
||||||
implicitWithdrawn := make([]*Path, 0, len(dest.knownPathList))
|
|
||||||
for _, path := range dest.knownPathList {
|
|
||||||
found := false
|
|
||||||
for _, newPath := range dest.newPathList {
|
|
||||||
if newPath.NoImplicitWithdraw() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Here we just check if source is same and not check if path
|
|
||||||
// version num. as newPaths are implicit withdrawal of old
|
|
||||||
// paths and when doing RouteRefresh (not EnhancedRouteRefresh)
|
|
||||||
// we get same paths again.
|
|
||||||
if newPath.GetSource().Equal(path.GetSource()) && newPath.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Key": dest.GetNlri().String(),
|
|
||||||
"Path": path,
|
|
||||||
}).Debug("Implicit withdrawal of old path, since we have learned new path from the same peer")
|
|
||||||
|
|
||||||
found = true
|
|
||||||
newPath.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found {
|
|
||||||
implicitWithdrawn = append(implicitWithdrawn, path)
|
|
||||||
} else {
|
|
||||||
newKnownPaths = append(newKnownPaths, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dest.knownPathList = newKnownPaths
|
|
||||||
return implicitWithdrawn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dest *Destination) computeKnownBestPath() (*Path, BestPathReason, error) {
|
|
||||||
if SelectionOptions.DisableBestPathSelection {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
}).Debug("computeKnownBestPath skipped")
|
|
||||||
return nil, BPR_DISABLED, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we do not have any paths to this destination, then we do not have
|
|
||||||
// new best path.
|
|
||||||
if len(dest.knownPathList) == 0 {
|
|
||||||
return nil, BPR_UNKNOWN, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
}).Debugf("computeKnownBestPath knownPathList: %d", len(dest.knownPathList))
|
|
||||||
|
|
||||||
// We pick the first path as current best path. This helps in breaking
|
|
||||||
// tie between two new paths learned in one cycle for which best-path
|
|
||||||
// calculation steps lead to tie.
|
|
||||||
if len(dest.knownPathList) == 1 {
|
|
||||||
// If the first path has the invalidated next-hop, which evaluated by
|
|
||||||
// IGP, returns no path with the reason of the next-hop reachability.
|
|
||||||
if dest.knownPathList[0].IsNexthopInvalid {
|
|
||||||
return nil, BPR_REACHABLE_NEXT_HOP, nil
|
|
||||||
}
|
|
||||||
return dest.knownPathList[0], BPR_ONLY_PATH, nil
|
|
||||||
}
|
|
||||||
sort.Sort(dest.knownPathList)
|
|
||||||
newBest := dest.knownPathList[0]
|
|
||||||
// If the first path has the invalidated next-hop, which evaluated by IGP,
|
|
||||||
// returns no path with the reason of the next-hop reachability.
|
|
||||||
if dest.knownPathList[0].IsNexthopInvalid {
|
|
||||||
return nil, BPR_REACHABLE_NEXT_HOP, nil
|
|
||||||
}
|
|
||||||
return newBest, newBest.reason, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type paths []*Path
|
|
||||||
|
|
||||||
func (p paths) Len() int {
|
|
||||||
return len(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p paths) Swap(i, j int) {
|
|
||||||
p[i], p[j] = p[j], p[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p paths) Less(i, j int) bool {
|
|
||||||
|
|
||||||
//Compares given paths and returns best path.
|
|
||||||
//
|
|
||||||
//Parameters:
|
|
||||||
// -`path1`: first path to compare
|
|
||||||
// -`path2`: second path to compare
|
|
||||||
//
|
|
||||||
// Best path processing will involve following steps:
|
|
||||||
// 1. Select a path with a reachable next hop.
|
|
||||||
// 2. Select the path with the highest weight.
|
|
||||||
// 3. If path weights are the same, select the path with the highest
|
|
||||||
// local preference value.
|
|
||||||
// 4. Prefer locally originated routes (network routes, redistributed
|
|
||||||
// routes, or aggregated routes) over received routes.
|
|
||||||
// 5. Select the route with the shortest AS-path length.
|
|
||||||
// 6. If all paths have the same AS-path length, select the path based
|
|
||||||
// on origin: IGP is preferred over EGP; EGP is preferred over
|
|
||||||
// Incomplete.
|
|
||||||
// 7. If the origins are the same, select the path with lowest MED
|
|
||||||
// value.
|
|
||||||
// 8. If the paths have the same MED values, select the path learned
|
|
||||||
// via EBGP over one learned via IBGP.
|
|
||||||
// 9. Select the route with the lowest IGP cost to the next hop.
|
|
||||||
// 10. Select the route received from the peer with the lowest BGP
|
|
||||||
// router ID.
|
|
||||||
//
|
|
||||||
// Returns None if best-path among given paths cannot be computed else best
|
|
||||||
// path.
|
|
||||||
// Assumes paths from NC has source equal to None.
|
|
||||||
//
|
|
||||||
|
|
||||||
path1 := p[i]
|
|
||||||
path2 := p[j]
|
|
||||||
|
|
||||||
var better *Path
|
|
||||||
reason := BPR_UNKNOWN
|
|
||||||
|
|
||||||
// draft-uttaro-idr-bgp-persistence-02
|
|
||||||
if better == nil {
|
|
||||||
better = compareByLLGRStaleCommunity(path1, path2)
|
|
||||||
reason = BPR_NON_LLGR_STALE
|
|
||||||
}
|
|
||||||
// Follow best path calculation algorithm steps.
|
|
||||||
// compare by reachability
|
|
||||||
if better == nil {
|
|
||||||
better = compareByReachableNexthop(path1, path2)
|
|
||||||
reason = BPR_REACHABLE_NEXT_HOP
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByHighestWeight(path1, path2)
|
|
||||||
reason = BPR_HIGHEST_WEIGHT
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByLocalPref(path1, path2)
|
|
||||||
reason = BPR_LOCAL_PREF
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByLocalOrigin(path1, path2)
|
|
||||||
reason = BPR_LOCAL_ORIGIN
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByASPath(path1, path2)
|
|
||||||
reason = BPR_ASPATH
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByOrigin(path1, path2)
|
|
||||||
reason = BPR_ORIGIN
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByMED(path1, path2)
|
|
||||||
reason = BPR_MED
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByASNumber(path1, path2)
|
|
||||||
reason = BPR_ASN
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByIGPCost(path1, path2)
|
|
||||||
reason = BPR_IGP_COST
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
better = compareByAge(path1, path2)
|
|
||||||
reason = BPR_OLDER
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
var e error = nil
|
|
||||||
better, e = compareByRouterID(path1, path2)
|
|
||||||
if e != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Table",
|
|
||||||
"Error": e,
|
|
||||||
}).Error("Could not get best path by comparing router ID")
|
|
||||||
}
|
|
||||||
reason = BPR_ROUTER_ID
|
|
||||||
}
|
|
||||||
if better == nil {
|
|
||||||
reason = BPR_UNKNOWN
|
|
||||||
better = path1
|
|
||||||
}
|
|
||||||
|
|
||||||
better.reason = reason
|
|
||||||
|
|
||||||
if better == path1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func compareByLLGRStaleCommunity(path1, path2 *Path) *Path {
|
func compareByLLGRStaleCommunity(path1, path2 *Path) *Path {
|
||||||
p1 := path1.IsLLGRStale()
|
p1 := path1.IsLLGRStale()
|
||||||
p2 := path2.IsLLGRStale()
|
p2 := path2.IsLLGRStale()
|
||||||
@ -1012,6 +971,7 @@ func (dest *Destination) String() string {
|
|||||||
|
|
||||||
type DestinationSelectOption struct {
|
type DestinationSelectOption struct {
|
||||||
ID string
|
ID string
|
||||||
|
AS uint32
|
||||||
VRF *Vrf
|
VRF *Vrf
|
||||||
adj bool
|
adj bool
|
||||||
Best bool
|
Best bool
|
||||||
@ -1022,12 +982,13 @@ func (d *Destination) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(d.GetAllKnownPathList())
|
return json.Marshal(d.GetAllKnownPathList())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (old *Destination) Select(option ...DestinationSelectOption) *Destination {
|
func (d *Destination) Select(option ...DestinationSelectOption) *Destination {
|
||||||
id := GLOBAL_RIB_NAME
|
id := GLOBAL_RIB_NAME
|
||||||
var vrf *Vrf
|
var vrf *Vrf
|
||||||
adj := false
|
adj := false
|
||||||
best := false
|
best := false
|
||||||
mp := false
|
mp := false
|
||||||
|
as := uint32(0)
|
||||||
for _, o := range option {
|
for _, o := range option {
|
||||||
if o.ID != "" {
|
if o.ID != "" {
|
||||||
id = o.ID
|
id = o.ID
|
||||||
@ -1038,12 +999,14 @@ func (old *Destination) Select(option ...DestinationSelectOption) *Destination {
|
|||||||
adj = o.adj
|
adj = o.adj
|
||||||
best = o.Best
|
best = o.Best
|
||||||
mp = o.MultiPath
|
mp = o.MultiPath
|
||||||
|
as = o.AS
|
||||||
}
|
}
|
||||||
var paths []*Path
|
var paths []*Path
|
||||||
if adj {
|
if adj {
|
||||||
paths = old.knownPathList
|
paths = make([]*Path, len(d.knownPathList))
|
||||||
|
copy(paths, d.knownPathList)
|
||||||
} else {
|
} else {
|
||||||
paths = old.GetKnownPathList(id)
|
paths = d.GetKnownPathList(id, as)
|
||||||
if vrf != nil {
|
if vrf != nil {
|
||||||
ps := make([]*Path, 0, len(paths))
|
ps := make([]*Path, 0, len(paths))
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
@ -1074,13 +1037,7 @@ func (old *Destination) Select(option ...DestinationSelectOption) *Destination {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new := NewDestination(old.nlri, 0)
|
return NewDestination(d.nlri, 0, paths...)
|
||||||
for _, path := range paths {
|
|
||||||
p := path.Clone(path.IsWithdraw)
|
|
||||||
p.Filter("", path.Filtered(id))
|
|
||||||
new.knownPathList = append(new.knownPathList, p)
|
|
||||||
}
|
|
||||||
return new
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type destinations []*Destination
|
type destinations []*Destination
|
||||||
|
|||||||
6
vendor/github.com/osrg/gobgp/table/message.go
generated
vendored
6
vendor/github.com/osrg/gobgp/table/message.go
generated
vendored
@ -201,9 +201,7 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
||||||
for _, p := range newParams {
|
newIntfParams = append(newIntfParams, newParams...)
|
||||||
newIntfParams = append(newIntfParams, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams)
|
msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams)
|
||||||
return nil
|
return nil
|
||||||
@ -384,7 +382,7 @@ func (p *packerV4) add(path *Path) {
|
|||||||
if cages, y := p.hashmap[key]; y {
|
if cages, y := p.hashmap[key]; y {
|
||||||
added := false
|
added := false
|
||||||
for _, c := range cages {
|
for _, c := range cages {
|
||||||
if bytes.Compare(c.attrsBytes, attrsB.Bytes()) == 0 {
|
if bytes.Equal(c.attrsBytes, attrsB.Bytes()) {
|
||||||
c.paths = append(c.paths, path)
|
c.paths = append(c.paths, path)
|
||||||
added = true
|
added = true
|
||||||
break
|
break
|
||||||
|
|||||||
110
vendor/github.com/osrg/gobgp/table/path.go
generated
vendored
110
vendor/github.com/osrg/gobgp/table/path.go
generated
vendored
@ -28,8 +28,6 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
|
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
)
|
)
|
||||||
@ -94,8 +92,6 @@ type originInfo struct {
|
|||||||
source *PeerInfo
|
source *PeerInfo
|
||||||
timestamp int64
|
timestamp int64
|
||||||
validation *Validation
|
validation *Validation
|
||||||
key string
|
|
||||||
uuid uuid.UUID
|
|
||||||
noImplicitWithdraw bool
|
noImplicitWithdraw bool
|
||||||
isFromExternal bool
|
isFromExternal bool
|
||||||
eor bool
|
eor bool
|
||||||
@ -139,17 +135,17 @@ type Validation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
info *originInfo
|
info *originInfo
|
||||||
IsWithdraw bool
|
parent *Path
|
||||||
pathAttrs []bgp.PathAttributeInterface
|
pathAttrs []bgp.PathAttributeInterface
|
||||||
attrsHash uint32
|
dels []bgp.BGPAttrType
|
||||||
reason BestPathReason
|
attrsHash uint32
|
||||||
parent *Path
|
aslooped bool
|
||||||
dels []bgp.BGPAttrType
|
reason BestPathReason
|
||||||
filtered map[string]PolicyDirection
|
|
||||||
VrfIds []uint16
|
|
||||||
// For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP.
|
// For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP.
|
||||||
IsNexthopInvalid bool
|
IsNexthopInvalid bool
|
||||||
|
IsWithdraw bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path {
|
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path {
|
||||||
@ -170,7 +166,6 @@ func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pa
|
|||||||
},
|
},
|
||||||
IsWithdraw: isWithdraw,
|
IsWithdraw: isWithdraw,
|
||||||
pathAttrs: pattrs,
|
pathAttrs: pattrs,
|
||||||
filtered: make(map[string]PolicyDirection),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +177,6 @@ func NewEOR(family bgp.RouteFamily) *Path {
|
|||||||
nlri: nlri,
|
nlri: nlri,
|
||||||
eor: true,
|
eor: true,
|
||||||
},
|
},
|
||||||
filtered: make(map[string]PolicyDirection),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,16 +290,16 @@ func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInf
|
|||||||
}
|
}
|
||||||
// When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST.
|
// When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST.
|
||||||
// If the CLUSTER_LIST is empty, it MUST create a new one.
|
// If the CLUSTER_LIST is empty, it MUST create a new one.
|
||||||
id := string(peer.RouteReflector.Config.RouteReflectorClusterId)
|
clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId)
|
||||||
if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil {
|
if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil {
|
||||||
path.setPathAttr(bgp.NewPathAttributeClusterList([]string{id}))
|
path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID}))
|
||||||
} else {
|
} else {
|
||||||
clusterList := p.(*bgp.PathAttributeClusterList)
|
clusterList := p.(*bgp.PathAttributeClusterList)
|
||||||
newClusterList := make([]string, 0, len(clusterList.Value))
|
newClusterList := make([]string, 0, len(clusterList.Value))
|
||||||
for _, ip := range clusterList.Value {
|
for _, ip := range clusterList.Value {
|
||||||
newClusterList = append(newClusterList, ip.String())
|
newClusterList = append(newClusterList, ip.String())
|
||||||
}
|
}
|
||||||
path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{id}, newClusterList...)))
|
path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +333,8 @@ func (path *Path) Clone(isWithdraw bool) *Path {
|
|||||||
return &Path{
|
return &Path{
|
||||||
parent: path,
|
parent: path,
|
||||||
IsWithdraw: isWithdraw,
|
IsWithdraw: isWithdraw,
|
||||||
filtered: make(map[string]PolicyDirection),
|
|
||||||
IsNexthopInvalid: path.IsNexthopInvalid,
|
IsNexthopInvalid: path.IsNexthopInvalid,
|
||||||
|
attrsHash: path.attrsHash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,26 +378,6 @@ func (path *Path) SetIsFromExternal(y bool) {
|
|||||||
path.OriginInfo().isFromExternal = y
|
path.OriginInfo().isFromExternal = y
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *Path) UUID() uuid.UUID {
|
|
||||||
return path.OriginInfo().uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (path *Path) SetUUID(id []byte) {
|
|
||||||
path.OriginInfo().uuid = uuid.FromBytesOrNil(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (path *Path) AssignNewUUID() {
|
|
||||||
path.OriginInfo().uuid, _ = uuid.NewV4()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (path *Path) Filter(id string, reason PolicyDirection) {
|
|
||||||
path.filtered[id] = reason
|
|
||||||
}
|
|
||||||
|
|
||||||
func (path *Path) Filtered(id string) PolicyDirection {
|
|
||||||
return path.filtered[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (path *Path) GetRouteFamily() bgp.RouteFamily {
|
func (path *Path) GetRouteFamily() bgp.RouteFamily {
|
||||||
return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI())
|
return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI())
|
||||||
}
|
}
|
||||||
@ -423,9 +397,17 @@ func (path *Path) IsStale() bool {
|
|||||||
return path.OriginInfo().stale
|
return path.OriginInfo().stale
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (path *Path) IsAsLooped() bool {
|
||||||
|
return path.aslooped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (path *Path) SetAsLooped(y bool) {
|
||||||
|
path.aslooped = y
|
||||||
|
}
|
||||||
|
|
||||||
func (path *Path) IsLLGRStale() bool {
|
func (path *Path) IsLLGRStale() bool {
|
||||||
for _, c := range path.GetCommunities() {
|
for _, c := range path.GetCommunities() {
|
||||||
if c == bgp.COMMUNITY_LLGR_STALE {
|
if c == uint32(bgp.COMMUNITY_LLGR_STALE) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,10 +584,7 @@ func (path *Path) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (path *Path) getPrefix() string {
|
func (path *Path) getPrefix() string {
|
||||||
if path.OriginInfo().key == "" {
|
return path.GetNlri().String()
|
||||||
path.OriginInfo().key = path.GetNlri().String()
|
|
||||||
}
|
|
||||||
return path.OriginInfo().key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *Path) GetAsPath() *bgp.PathAttributeAsPath {
|
func (path *Path) GetAsPath() *bgp.PathAttributeAsPath {
|
||||||
@ -819,7 +798,6 @@ func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsO
|
|||||||
}
|
}
|
||||||
path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
|
path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *Path) removeConfedAs() {
|
func (path *Path) removeConfedAs() {
|
||||||
@ -946,9 +924,7 @@ func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface {
|
|||||||
eCommunityList := make([]bgp.ExtendedCommunityInterface, 0)
|
eCommunityList := make([]bgp.ExtendedCommunityInterface, 0)
|
||||||
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil {
|
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil {
|
||||||
eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value
|
eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value
|
||||||
for _, eCommunity := range eCommunities {
|
eCommunityList = append(eCommunityList, eCommunities...)
|
||||||
eCommunityList = append(eCommunityList, eCommunity)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return eCommunityList
|
return eCommunityList
|
||||||
}
|
}
|
||||||
@ -972,9 +948,7 @@ func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity {
|
|||||||
if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil {
|
if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil {
|
||||||
v := a.(*bgp.PathAttributeLargeCommunities).Values
|
v := a.(*bgp.PathAttributeLargeCommunities).Values
|
||||||
ret := make([]*bgp.LargeCommunity, 0, len(v))
|
ret := make([]*bgp.LargeCommunity, 0, len(v))
|
||||||
for _, c := range v {
|
ret = append(ret, v...)
|
||||||
ret = append(ret, c)
|
|
||||||
}
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -1000,20 +974,19 @@ func (path *Path) GetMed() (uint32, error) {
|
|||||||
|
|
||||||
// SetMed replace, add or subtraction med with new ones.
|
// SetMed replace, add or subtraction med with new ones.
|
||||||
func (path *Path) SetMed(med int64, doReplace bool) error {
|
func (path *Path) SetMed(med int64, doReplace bool) error {
|
||||||
|
|
||||||
parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) {
|
parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) {
|
||||||
newMed := &bgp.PathAttributeMultiExitDisc{}
|
|
||||||
if doReplace {
|
if doReplace {
|
||||||
newMed = bgp.NewPathAttributeMultiExitDisc(uint32(med))
|
return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil
|
||||||
} else {
|
|
||||||
if int64(orgMed)+med < 0 {
|
|
||||||
return nil, fmt.Errorf("med value invalid. it's underflow threshold.")
|
|
||||||
} else if int64(orgMed)+med > int64(math.MaxUint32) {
|
|
||||||
return nil, fmt.Errorf("med value invalid. it's overflow threshold.")
|
|
||||||
}
|
|
||||||
newMed = bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med))
|
|
||||||
}
|
}
|
||||||
return newMed, nil
|
|
||||||
|
medVal := int64(orgMed) + med
|
||||||
|
if medVal < 0 {
|
||||||
|
return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal)
|
||||||
|
} else if medVal > int64(math.MaxUint32) {
|
||||||
|
return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
m := uint32(0)
|
m := uint32(0)
|
||||||
@ -1094,7 +1067,6 @@ func (path *Path) MarshalJSON() ([]byte, error) {
|
|||||||
SourceID net.IP `json:"source-id,omitempty"`
|
SourceID net.IP `json:"source-id,omitempty"`
|
||||||
NeighborIP net.IP `json:"neighbor-ip,omitempty"`
|
NeighborIP net.IP `json:"neighbor-ip,omitempty"`
|
||||||
Stale bool `json:"stale,omitempty"`
|
Stale bool `json:"stale,omitempty"`
|
||||||
Filtered bool `json:"filtered,omitempty"`
|
|
||||||
UUID string `json:"uuid,omitempty"`
|
UUID string `json:"uuid,omitempty"`
|
||||||
ID uint32 `json:"id,omitempty"`
|
ID uint32 `json:"id,omitempty"`
|
||||||
}{
|
}{
|
||||||
@ -1106,8 +1078,6 @@ func (path *Path) MarshalJSON() ([]byte, error) {
|
|||||||
SourceID: path.GetSource().ID,
|
SourceID: path.GetSource().ID,
|
||||||
NeighborIP: path.GetSource().Address,
|
NeighborIP: path.GetSource().Address,
|
||||||
Stale: path.IsStale(),
|
Stale: path.IsStale(),
|
||||||
Filtered: path.Filtered("") > POLICY_DIRECTION_NONE,
|
|
||||||
UUID: path.UUID().String(),
|
|
||||||
ID: path.GetNlri().PathIdentifier(),
|
ID: path.GetNlri().PathIdentifier(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1153,10 +1123,14 @@ func (v *Vrf) ToGlobalPath(path *Path) error {
|
|||||||
switch rf := path.GetRouteFamily(); rf {
|
switch rf := path.GetRouteFamily(); rf {
|
||||||
case bgp.RF_IPv4_UC:
|
case bgp.RF_IPv4_UC:
|
||||||
n := nlri.(*bgp.IPAddrPrefix)
|
n := nlri.(*bgp.IPAddrPrefix)
|
||||||
|
pathIdentifier := path.GetNlri().PathIdentifier()
|
||||||
path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
|
path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
|
||||||
|
path.GetNlri().SetPathIdentifier(pathIdentifier)
|
||||||
case bgp.RF_IPv6_UC:
|
case bgp.RF_IPv6_UC:
|
||||||
n := nlri.(*bgp.IPv6AddrPrefix)
|
n := nlri.(*bgp.IPv6AddrPrefix)
|
||||||
|
pathIdentifier := path.GetNlri().PathIdentifier()
|
||||||
path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
|
path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
|
||||||
|
path.GetNlri().SetPathIdentifier(pathIdentifier)
|
||||||
case bgp.RF_EVPN:
|
case bgp.RF_EVPN:
|
||||||
n := nlri.(*bgp.EVPNNLRI)
|
n := nlri.(*bgp.EVPNNLRI)
|
||||||
switch n.RouteType {
|
switch n.RouteType {
|
||||||
@ -1175,13 +1149,16 @@ func (v *Vrf) ToGlobalPath(path *Path) error {
|
|||||||
func (p *Path) ToGlobal(vrf *Vrf) *Path {
|
func (p *Path) ToGlobal(vrf *Vrf) *Path {
|
||||||
nlri := p.GetNlri()
|
nlri := p.GetNlri()
|
||||||
nh := p.GetNexthop()
|
nh := p.GetNexthop()
|
||||||
|
pathId := nlri.PathIdentifier()
|
||||||
switch rf := p.GetRouteFamily(); rf {
|
switch rf := p.GetRouteFamily(); rf {
|
||||||
case bgp.RF_IPv4_UC:
|
case bgp.RF_IPv4_UC:
|
||||||
n := nlri.(*bgp.IPAddrPrefix)
|
n := nlri.(*bgp.IPAddrPrefix)
|
||||||
nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
|
nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
|
||||||
|
nlri.SetPathIdentifier(pathId)
|
||||||
case bgp.RF_IPv6_UC:
|
case bgp.RF_IPv6_UC:
|
||||||
n := nlri.(*bgp.IPv6AddrPrefix)
|
n := nlri.(*bgp.IPv6AddrPrefix)
|
||||||
nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
|
nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
|
||||||
|
nlri.SetPathIdentifier(pathId)
|
||||||
case bgp.RF_EVPN:
|
case bgp.RF_EVPN:
|
||||||
n := nlri.(*bgp.EVPNNLRI)
|
n := nlri.(*bgp.EVPNNLRI)
|
||||||
switch n.RouteType {
|
switch n.RouteType {
|
||||||
@ -1222,17 +1199,20 @@ func (p *Path) ToGlobal(vrf *Vrf) *Path {
|
|||||||
func (p *Path) ToLocal() *Path {
|
func (p *Path) ToLocal() *Path {
|
||||||
nlri := p.GetNlri()
|
nlri := p.GetNlri()
|
||||||
f := p.GetRouteFamily()
|
f := p.GetRouteFamily()
|
||||||
|
pathId := nlri.PathLocalIdentifier()
|
||||||
switch f {
|
switch f {
|
||||||
case bgp.RF_IPv4_VPN:
|
case bgp.RF_IPv4_VPN:
|
||||||
n := nlri.(*bgp.LabeledVPNIPAddrPrefix)
|
n := nlri.(*bgp.LabeledVPNIPAddrPrefix)
|
||||||
_, c, _ := net.ParseCIDR(n.IPPrefix())
|
_, c, _ := net.ParseCIDR(n.IPPrefix())
|
||||||
ones, _ := c.Mask.Size()
|
ones, _ := c.Mask.Size()
|
||||||
nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String())
|
nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String())
|
||||||
|
nlri.SetPathLocalIdentifier(pathId)
|
||||||
case bgp.RF_IPv6_VPN:
|
case bgp.RF_IPv6_VPN:
|
||||||
n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix)
|
n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix)
|
||||||
_, c, _ := net.ParseCIDR(n.IPPrefix())
|
_, c, _ := net.ParseCIDR(n.IPPrefix())
|
||||||
ones, _ := c.Mask.Size()
|
ones, _ := c.Mask.Size()
|
||||||
nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String())
|
nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String())
|
||||||
|
nlri.SetPathLocalIdentifier(pathId)
|
||||||
default:
|
default:
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|||||||
393
vendor/github.com/osrg/gobgp/table/policy.go
generated
vendored
393
vendor/github.com/osrg/gobgp/table/policy.go
generated
vendored
@ -26,16 +26,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
radix "github.com/armon/go-radix"
|
|
||||||
|
|
||||||
"github.com/osrg/gobgp/config"
|
"github.com/osrg/gobgp/config"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
|
|
||||||
|
radix "github.com/armon/go-radix"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PolicyOptions struct {
|
type PolicyOptions struct {
|
||||||
Info *PeerInfo
|
Info *PeerInfo
|
||||||
|
ValidationResult *Validation
|
||||||
|
OldNextHop net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefinedType int
|
type DefinedType int
|
||||||
@ -48,6 +49,7 @@ const (
|
|||||||
DEFINED_TYPE_COMMUNITY
|
DEFINED_TYPE_COMMUNITY
|
||||||
DEFINED_TYPE_EXT_COMMUNITY
|
DEFINED_TYPE_EXT_COMMUNITY
|
||||||
DEFINED_TYPE_LARGE_COMMUNITY
|
DEFINED_TYPE_LARGE_COMMUNITY
|
||||||
|
DEFINED_TYPE_NEXT_HOP
|
||||||
)
|
)
|
||||||
|
|
||||||
type RouteType int
|
type RouteType int
|
||||||
@ -153,6 +155,8 @@ const (
|
|||||||
CONDITION_RPKI
|
CONDITION_RPKI
|
||||||
CONDITION_ROUTE_TYPE
|
CONDITION_ROUTE_TYPE
|
||||||
CONDITION_LARGE_COMMUNITY
|
CONDITION_LARGE_COMMUNITY
|
||||||
|
CONDITION_NEXT_HOP
|
||||||
|
CONDITION_AFI_SAFI_IN
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionType int
|
type ActionType int
|
||||||
@ -305,6 +309,8 @@ func (p *Prefix) PrefixString() string {
|
|||||||
return p.Prefix.String()
|
return p.Prefix.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _regexpPrefixRange = regexp.MustCompile(`(\d+)\.\.(\d+)`)
|
||||||
|
|
||||||
func NewPrefix(c config.Prefix) (*Prefix, error) {
|
func NewPrefix(c config.Prefix) (*Prefix, error) {
|
||||||
_, prefix, err := net.ParseCIDR(c.IpPrefix)
|
_, prefix, err := net.ParseCIDR(c.IpPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -320,28 +326,30 @@ func NewPrefix(c config.Prefix) (*Prefix, error) {
|
|||||||
AddressFamily: rf,
|
AddressFamily: rf,
|
||||||
}
|
}
|
||||||
maskRange := c.MasklengthRange
|
maskRange := c.MasklengthRange
|
||||||
|
|
||||||
if maskRange == "" {
|
if maskRange == "" {
|
||||||
l, _ := prefix.Mask.Size()
|
l, _ := prefix.Mask.Size()
|
||||||
maskLength := uint8(l)
|
maskLength := uint8(l)
|
||||||
p.MasklengthRangeMax = maskLength
|
p.MasklengthRangeMax = maskLength
|
||||||
p.MasklengthRangeMin = maskLength
|
p.MasklengthRangeMin = maskLength
|
||||||
} else {
|
return p, nil
|
||||||
exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
|
|
||||||
elems := exp.FindStringSubmatch(maskRange)
|
|
||||||
if len(elems) != 3 {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Policy",
|
|
||||||
"Type": "Prefix",
|
|
||||||
"MaskRangeFormat": maskRange,
|
|
||||||
}).Warn("mask length range format is invalid.")
|
|
||||||
return nil, fmt.Errorf("mask length range format is invalid")
|
|
||||||
}
|
|
||||||
// we've already checked the range is sane by regexp
|
|
||||||
min, _ := strconv.ParseUint(elems[1], 10, 8)
|
|
||||||
max, _ := strconv.ParseUint(elems[2], 10, 8)
|
|
||||||
p.MasklengthRangeMin = uint8(min)
|
|
||||||
p.MasklengthRangeMax = uint8(max)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elems := _regexpPrefixRange.FindStringSubmatch(maskRange)
|
||||||
|
if len(elems) != 3 {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Policy",
|
||||||
|
"Type": "Prefix",
|
||||||
|
"MaskRangeFormat": maskRange,
|
||||||
|
}).Warn("mask length range format is invalid.")
|
||||||
|
return nil, fmt.Errorf("mask length range format is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// we've already checked the range is sane by regexp
|
||||||
|
min, _ := strconv.ParseUint(elems[1], 10, 8)
|
||||||
|
max, _ := strconv.ParseUint(elems[2], 10, 8)
|
||||||
|
p.MasklengthRangeMin = uint8(min)
|
||||||
|
p.MasklengthRangeMax = uint8(max)
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,6 +542,109 @@ func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NextHopSet struct {
|
||||||
|
list []net.IPNet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) Name() string {
|
||||||
|
return "NextHopSet: NO NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) Type() DefinedType {
|
||||||
|
return DEFINED_TYPE_NEXT_HOP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lhs *NextHopSet) Append(arg DefinedSet) error {
|
||||||
|
rhs, ok := arg.(*NextHopSet)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("type cast failed")
|
||||||
|
}
|
||||||
|
lhs.list = append(lhs.list, rhs.list...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lhs *NextHopSet) Remove(arg DefinedSet) error {
|
||||||
|
rhs, ok := arg.(*NextHopSet)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("type cast failed")
|
||||||
|
}
|
||||||
|
ps := make([]net.IPNet, 0, len(lhs.list))
|
||||||
|
for _, x := range lhs.list {
|
||||||
|
found := false
|
||||||
|
for _, y := range rhs.list {
|
||||||
|
if x.String() == y.String() {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
ps = append(ps, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lhs.list = ps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lhs *NextHopSet) Replace(arg DefinedSet) error {
|
||||||
|
rhs, ok := arg.(*NextHopSet)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("type cast failed")
|
||||||
|
}
|
||||||
|
lhs.list = rhs.list
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) List() []string {
|
||||||
|
list := make([]string, 0, len(s.list))
|
||||||
|
for _, n := range s.list {
|
||||||
|
list = append(list, n.String())
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) ToConfig() []string {
|
||||||
|
return s.List()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) String() string {
|
||||||
|
return "[ " + strings.Join(s.List(), ", ") + " ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NextHopSet) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(s.ToConfig())
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNextHopSetFromApiStruct(name string, list []net.IPNet) (*NextHopSet, error) {
|
||||||
|
return &NextHopSet{
|
||||||
|
list: list,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNextHopSet(c []string) (*NextHopSet, error) {
|
||||||
|
list := make([]net.IPNet, 0, len(c))
|
||||||
|
for _, x := range c {
|
||||||
|
_, cidr, err := net.ParseCIDR(x)
|
||||||
|
if err != nil {
|
||||||
|
addr := net.ParseIP(x)
|
||||||
|
if addr == nil {
|
||||||
|
return nil, fmt.Errorf("invalid address or prefix: %s", x)
|
||||||
|
}
|
||||||
|
mask := net.CIDRMask(32, 32)
|
||||||
|
if addr.To4() == nil {
|
||||||
|
mask = net.CIDRMask(128, 128)
|
||||||
|
}
|
||||||
|
cidr = &net.IPNet{
|
||||||
|
IP: addr,
|
||||||
|
Mask: mask,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list = append(list, *cidr)
|
||||||
|
}
|
||||||
|
return &NextHopSet{
|
||||||
|
list: list,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type NeighborSet struct {
|
type NeighborSet struct {
|
||||||
name string
|
name string
|
||||||
list []net.IPNet
|
list []net.IPNet
|
||||||
@ -709,32 +820,35 @@ func (m *singleAsPathMatch) Match(aspath []uint32) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_regexpLeftMostRe = regexp.MustCompile(`$\^([0-9]+)_^`)
|
||||||
|
_regexpOriginRe = regexp.MustCompile(`^_([0-9]+)\$$`)
|
||||||
|
_regexpIncludeRe = regexp.MustCompile("^_([0-9]+)_$")
|
||||||
|
_regexpOnlyRe = regexp.MustCompile(`^\^([0-9]+)\$$`)
|
||||||
|
)
|
||||||
|
|
||||||
func NewSingleAsPathMatch(arg string) *singleAsPathMatch {
|
func NewSingleAsPathMatch(arg string) *singleAsPathMatch {
|
||||||
leftMostRe := regexp.MustCompile("$\\^([0-9]+)_^")
|
|
||||||
originRe := regexp.MustCompile("^_([0-9]+)\\$$")
|
|
||||||
includeRe := regexp.MustCompile("^_([0-9]+)_$")
|
|
||||||
onlyRe := regexp.MustCompile("^\\^([0-9]+)\\$$")
|
|
||||||
switch {
|
switch {
|
||||||
case leftMostRe.MatchString(arg):
|
case _regexpLeftMostRe.MatchString(arg):
|
||||||
asn, _ := strconv.ParseUint(leftMostRe.FindStringSubmatch(arg)[1], 10, 32)
|
asn, _ := strconv.ParseUint(_regexpLeftMostRe.FindStringSubmatch(arg)[1], 10, 32)
|
||||||
return &singleAsPathMatch{
|
return &singleAsPathMatch{
|
||||||
asn: uint32(asn),
|
asn: uint32(asn),
|
||||||
mode: LEFT_MOST,
|
mode: LEFT_MOST,
|
||||||
}
|
}
|
||||||
case originRe.MatchString(arg):
|
case _regexpOriginRe.MatchString(arg):
|
||||||
asn, _ := strconv.ParseUint(originRe.FindStringSubmatch(arg)[1], 10, 32)
|
asn, _ := strconv.ParseUint(_regexpOriginRe.FindStringSubmatch(arg)[1], 10, 32)
|
||||||
return &singleAsPathMatch{
|
return &singleAsPathMatch{
|
||||||
asn: uint32(asn),
|
asn: uint32(asn),
|
||||||
mode: ORIGIN,
|
mode: ORIGIN,
|
||||||
}
|
}
|
||||||
case includeRe.MatchString(arg):
|
case _regexpIncludeRe.MatchString(arg):
|
||||||
asn, _ := strconv.ParseUint(includeRe.FindStringSubmatch(arg)[1], 10, 32)
|
asn, _ := strconv.ParseUint(_regexpIncludeRe.FindStringSubmatch(arg)[1], 10, 32)
|
||||||
return &singleAsPathMatch{
|
return &singleAsPathMatch{
|
||||||
asn: uint32(asn),
|
asn: uint32(asn),
|
||||||
mode: INCLUDE,
|
mode: INCLUDE,
|
||||||
}
|
}
|
||||||
case onlyRe.MatchString(arg):
|
case _regexpOnlyRe.MatchString(arg):
|
||||||
asn, _ := strconv.ParseUint(onlyRe.FindStringSubmatch(arg)[1], 10, 32)
|
asn, _ := strconv.ParseUint(_regexpOnlyRe.FindStringSubmatch(arg)[1], 10, 32)
|
||||||
return &singleAsPathMatch{
|
return &singleAsPathMatch{
|
||||||
asn: uint32(asn),
|
asn: uint32(asn),
|
||||||
mode: ONLY,
|
mode: ONLY,
|
||||||
@ -977,13 +1091,15 @@ func (s *CommunitySet) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(s.ToConfig())
|
return json.Marshal(s.ToConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _regexpCommunity = regexp.MustCompile(`(\d+):(\d+)`)
|
||||||
|
|
||||||
func ParseCommunity(arg string) (uint32, error) {
|
func ParseCommunity(arg string) (uint32, error) {
|
||||||
i, err := strconv.ParseUint(arg, 10, 32)
|
i, err := strconv.ParseUint(arg, 10, 32)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return uint32(i), nil
|
return uint32(i), nil
|
||||||
}
|
}
|
||||||
exp := regexp.MustCompile("(\\d+):(\\d+)")
|
|
||||||
elems := exp.FindStringSubmatch(arg)
|
elems := _regexpCommunity.FindStringSubmatch(arg)
|
||||||
if len(elems) == 3 {
|
if len(elems) == 3 {
|
||||||
fst, _ := strconv.ParseUint(elems[1], 10, 16)
|
fst, _ := strconv.ParseUint(elems[1], 10, 16)
|
||||||
snd, _ := strconv.ParseUint(elems[2], 10, 16)
|
snd, _ := strconv.ParseUint(elems[2], 10, 16)
|
||||||
@ -1028,24 +1144,25 @@ func ParseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
|
|||||||
return bgp.ParseExtendedCommunity(subtype, value)
|
return bgp.ParseExtendedCommunity(subtype, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _regexpCommunity2 = regexp.MustCompile(`(\d+.)*\d+:\d+`)
|
||||||
|
|
||||||
func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
||||||
i, err := strconv.ParseUint(arg, 10, 32)
|
i, err := strconv.ParseUint(arg, 10, 32)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil
|
return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
|
||||||
}
|
}
|
||||||
if regexp.MustCompile("(\\d+.)*\\d+:\\d+").MatchString(arg) {
|
|
||||||
return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil
|
if _regexpCommunity2.MatchString(arg) {
|
||||||
|
return regexp.Compile(fmt.Sprintf("^%s$", arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v := range bgp.WellKnownCommunityNameMap {
|
for i, v := range bgp.WellKnownCommunityNameMap {
|
||||||
if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v {
|
if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v {
|
||||||
return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil
|
return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exp, err := regexp.Compile(arg)
|
|
||||||
if err != nil {
|
return regexp.Compile(arg)
|
||||||
return nil, fmt.Errorf("invalid community format: %s", arg)
|
|
||||||
}
|
|
||||||
return exp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
|
func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
|
||||||
@ -1196,14 +1313,17 @@ func (s *LargeCommunitySet) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(s.ToConfig())
|
return json.Marshal(s.ToConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _regexpCommunityLarge = regexp.MustCompile(`\d+:\d+:\d+`)
|
||||||
|
|
||||||
func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
||||||
if regexp.MustCompile("\\d+:\\d+:\\d+").MatchString(arg) {
|
if _regexpCommunityLarge.MatchString(arg) {
|
||||||
return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil
|
return regexp.Compile(fmt.Sprintf("^%s$", arg))
|
||||||
}
|
}
|
||||||
exp, err := regexp.Compile(arg)
|
exp, err := regexp.Compile(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid large-community format: %s", arg)
|
return nil, fmt.Errorf("invalid large-community format: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return exp, nil
|
return exp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1239,6 +1359,74 @@ type Condition interface {
|
|||||||
Set() DefinedSet
|
Set() DefinedSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NextHopCondition struct {
|
||||||
|
set *NextHopSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *NextHopCondition) Type() ConditionType {
|
||||||
|
return CONDITION_NEXT_HOP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *NextHopCondition) Set() DefinedSet {
|
||||||
|
return c.set
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *NextHopCondition) Name() string { return "" }
|
||||||
|
|
||||||
|
func (c *NextHopCondition) String() string {
|
||||||
|
return c.set.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare next-hop ipaddress of this condition and source address of path
|
||||||
|
// and, subsequent comparisons are skipped if that matches the conditions.
|
||||||
|
// If NextHopSet's length is zero, return true.
|
||||||
|
func (c *NextHopCondition) Evaluate(path *Path, options *PolicyOptions) bool {
|
||||||
|
if len(c.set.list) == 0 {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Policy",
|
||||||
|
}).Debug("NextHop doesn't have elements")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
nexthop := path.GetNexthop()
|
||||||
|
|
||||||
|
// In cases where we advertise routes from iBGP to eBGP, we want to filter
|
||||||
|
// on the "original" nexthop. The current paths' nexthop has already been
|
||||||
|
// set and is ready to be advertised as per:
|
||||||
|
// https://tools.ietf.org/html/rfc4271#section-5.1.3
|
||||||
|
if options != nil && options.OldNextHop != nil &&
|
||||||
|
!options.OldNextHop.IsUnspecified() && !options.OldNextHop.Equal(nexthop) {
|
||||||
|
nexthop = options.OldNextHop
|
||||||
|
}
|
||||||
|
|
||||||
|
if nexthop == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range c.set.list {
|
||||||
|
if n.Contains(nexthop) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNextHopCondition(c []string) (*NextHopCondition, error) {
|
||||||
|
if len(c) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := NewNextHopSet(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &NextHopCondition{
|
||||||
|
set: list,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type PrefixCondition struct {
|
type PrefixCondition struct {
|
||||||
set *PrefixSet
|
set *PrefixSet
|
||||||
option MatchOption
|
option MatchOption
|
||||||
@ -1712,8 +1900,11 @@ func (c *RpkiValidationCondition) Type() ConditionType {
|
|||||||
return CONDITION_RPKI
|
return CONDITION_RPKI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RpkiValidationCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
|
func (c *RpkiValidationCondition) Evaluate(path *Path, options *PolicyOptions) bool {
|
||||||
return c.result == path.ValidationStatus()
|
if options != nil && options.ValidationResult != nil {
|
||||||
|
return c.result == options.ValidationResult.Status
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RpkiValidationCondition) Set() DefinedSet {
|
func (c *RpkiValidationCondition) Set() DefinedSet {
|
||||||
@ -1777,6 +1968,58 @@ func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AfiSafiInCondition struct {
|
||||||
|
routeFamilies []bgp.RouteFamily
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AfiSafiInCondition) Type() ConditionType {
|
||||||
|
return CONDITION_AFI_SAFI_IN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AfiSafiInCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
|
||||||
|
for _, rf := range c.routeFamilies {
|
||||||
|
if path.GetRouteFamily() == rf {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AfiSafiInCondition) Set() DefinedSet {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AfiSafiInCondition) Name() string { return "" }
|
||||||
|
|
||||||
|
func (c *AfiSafiInCondition) String() string {
|
||||||
|
tmp := make([]string, 0, len(c.routeFamilies))
|
||||||
|
for _, afiSafi := range c.routeFamilies {
|
||||||
|
tmp = append(tmp, afiSafi.String())
|
||||||
|
}
|
||||||
|
return strings.Join(tmp, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAfiSafiInCondition(afiSafInConfig []config.AfiSafiType) (*AfiSafiInCondition, error) {
|
||||||
|
if afiSafInConfig == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
routeFamilies := make([]bgp.RouteFamily, 0, len(afiSafInConfig))
|
||||||
|
for _, afiSafiValue := range afiSafInConfig {
|
||||||
|
if err := afiSafiValue.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rf, err := bgp.GetRouteFamily(string(afiSafiValue))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
routeFamilies = append(routeFamilies, rf)
|
||||||
|
}
|
||||||
|
return &AfiSafiInCondition{
|
||||||
|
routeFamilies: routeFamilies,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type Action interface {
|
type Action interface {
|
||||||
Type() ActionType
|
Type() ActionType
|
||||||
Apply(*Path, *PolicyOptions) *Path
|
Apply(*Path, *PolicyOptions) *Path
|
||||||
@ -1841,7 +2084,7 @@ func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if match == false {
|
if !match {
|
||||||
newComms = append(newComms, comm)
|
newComms = append(newComms, comm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1864,7 +2107,7 @@ func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bg
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if match == false {
|
if !match {
|
||||||
newComms = append(newComms, comm)
|
newComms = append(newComms, comm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1883,7 +2126,7 @@ func RegexpRemoveLargeCommunities(path *Path, exps []*regexp.Regexp) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if match == false {
|
if !match {
|
||||||
newComms = append(newComms, comm)
|
newComms = append(newComms, comm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1925,10 +2168,12 @@ func (a *CommunityAction) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(a.ToConfig())
|
return json.Marshal(a.ToConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this is not efficient use of regexp, probably slow
|
||||||
|
var _regexpCommunityReplaceString = regexp.MustCompile(`[\^\$]`)
|
||||||
|
|
||||||
func (a *CommunityAction) String() string {
|
func (a *CommunityAction) String() string {
|
||||||
list := a.ToConfig().SetCommunityMethod.CommunitiesList
|
list := a.ToConfig().SetCommunityMethod.CommunitiesList
|
||||||
exp := regexp.MustCompile("[\\^\\$]")
|
l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
|
||||||
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
|
|
||||||
return fmt.Sprintf("%s[%s]", a.action, l)
|
return fmt.Sprintf("%s[%s]", a.action, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2022,8 +2267,7 @@ func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity {
|
|||||||
|
|
||||||
func (a *ExtCommunityAction) String() string {
|
func (a *ExtCommunityAction) String() string {
|
||||||
list := a.ToConfig().SetExtCommunityMethod.CommunitiesList
|
list := a.ToConfig().SetExtCommunityMethod.CommunitiesList
|
||||||
exp := regexp.MustCompile("[\\^\\$]")
|
l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
|
||||||
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
|
|
||||||
return fmt.Sprintf("%s[%s]", a.action, l)
|
return fmt.Sprintf("%s[%s]", a.action, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2111,8 +2355,7 @@ func (a *LargeCommunityAction) ToConfig() *config.SetLargeCommunity {
|
|||||||
|
|
||||||
func (a *LargeCommunityAction) String() string {
|
func (a *LargeCommunityAction) String() string {
|
||||||
list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList
|
list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList
|
||||||
exp := regexp.MustCompile("[\\^\\$]")
|
l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
|
||||||
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
|
|
||||||
return fmt.Sprintf("%s[%s]", a.action, l)
|
return fmt.Sprintf("%s[%s]", a.action, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2201,12 +2444,14 @@ func (a *MedAction) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(a.ToConfig())
|
return json.Marshal(a.ToConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _regexpParseMedAction = regexp.MustCompile(`^(\+|\-)?(\d+)$`)
|
||||||
|
|
||||||
func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
|
func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
|
||||||
if string(c) == "" {
|
if string(c) == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
exp := regexp.MustCompile("^(\\+|\\-)?(\\d+)$")
|
|
||||||
elems := exp.FindStringSubmatch(string(c))
|
elems := _regexpParseMedAction.FindStringSubmatch(string(c))
|
||||||
if len(elems) != 3 {
|
if len(elems) != 3 {
|
||||||
return nil, fmt.Errorf("invalid med action format")
|
return nil, fmt.Errorf("invalid med action format")
|
||||||
}
|
}
|
||||||
@ -2465,12 +2710,22 @@ func (s *Statement) ToConfig() *config.Statement {
|
|||||||
case *LargeCommunityCondition:
|
case *LargeCommunityCondition:
|
||||||
v := c.(*LargeCommunityCondition)
|
v := c.(*LargeCommunityCondition)
|
||||||
cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
|
cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
|
||||||
|
case *NextHopCondition:
|
||||||
|
v := c.(*NextHopCondition)
|
||||||
|
cond.BgpConditions.NextHopInList = v.set.List()
|
||||||
case *RpkiValidationCondition:
|
case *RpkiValidationCondition:
|
||||||
v := c.(*RpkiValidationCondition)
|
v := c.(*RpkiValidationCondition)
|
||||||
cond.BgpConditions.RpkiValidationResult = v.result
|
cond.BgpConditions.RpkiValidationResult = v.result
|
||||||
case *RouteTypeCondition:
|
case *RouteTypeCondition:
|
||||||
v := c.(*RouteTypeCondition)
|
v := c.(*RouteTypeCondition)
|
||||||
cond.BgpConditions.RouteType = v.typ
|
cond.BgpConditions.RouteType = v.typ
|
||||||
|
case *AfiSafiInCondition:
|
||||||
|
v := c.(*AfiSafiInCondition)
|
||||||
|
res := make([]config.AfiSafiType, 0, len(v.routeFamilies))
|
||||||
|
for _, rf := range v.routeFamilies {
|
||||||
|
res = append(res, config.AfiSafiType(rf.String()))
|
||||||
|
}
|
||||||
|
cond.BgpConditions.AfiSafiInList = res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cond
|
return cond
|
||||||
@ -2669,6 +2924,12 @@ func NewStatement(c config.Statement) (*Statement, error) {
|
|||||||
func() (Condition, error) {
|
func() (Condition, error) {
|
||||||
return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet)
|
return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet)
|
||||||
},
|
},
|
||||||
|
func() (Condition, error) {
|
||||||
|
return NewNextHopCondition(c.Conditions.BgpConditions.NextHopInList)
|
||||||
|
},
|
||||||
|
func() (Condition, error) {
|
||||||
|
return NewAfiSafiInCondition(c.Conditions.BgpConditions.AfiSafiInList)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cs = make([]Condition, 0, len(cfs))
|
cs = make([]Condition, 0, len(cfs))
|
||||||
for _, f := range cfs {
|
for _, f := range cfs {
|
||||||
@ -2863,9 +3124,7 @@ func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path
|
|||||||
if before == nil {
|
if before == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if filtered := before.Filtered(id); filtered > POLICY_DIRECTION_NONE && filtered < dir {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if before.IsWithdraw {
|
if before.IsWithdraw {
|
||||||
return before
|
return before
|
||||||
}
|
}
|
||||||
@ -3044,6 +3303,8 @@ func (r *RoutingPolicy) validateCondition(v Condition) (err error) {
|
|||||||
c := v.(*LargeCommunityCondition)
|
c := v.(*LargeCommunityCondition)
|
||||||
c.set = i.(*LargeCommunitySet)
|
c.set = i.(*LargeCommunitySet)
|
||||||
}
|
}
|
||||||
|
case CONDITION_NEXT_HOP:
|
||||||
|
case CONDITION_AFI_SAFI_IN:
|
||||||
case CONDITION_AS_PATH_LENGTH:
|
case CONDITION_AS_PATH_LENGTH:
|
||||||
case CONDITION_RPKI:
|
case CONDITION_RPKI:
|
||||||
}
|
}
|
||||||
@ -3153,6 +3414,7 @@ func (r *RoutingPolicy) reload(c config.RoutingPolicy) error {
|
|||||||
}
|
}
|
||||||
dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y
|
dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y
|
||||||
}
|
}
|
||||||
|
|
||||||
pmap := make(map[string]*Policy)
|
pmap := make(map[string]*Policy)
|
||||||
smap := make(map[string]*Statement)
|
smap := make(map[string]*Statement)
|
||||||
for _, x := range c.PolicyDefinitions {
|
for _, x := range c.PolicyDefinitions {
|
||||||
@ -3352,6 +3614,11 @@ func (r *RoutingPolicy) ReplaceStatement(st *Statement) (err error) {
|
|||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
for _, c := range st.Conditions {
|
||||||
|
if err = r.validateCondition(c); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
m := r.statementMap
|
m := r.statementMap
|
||||||
name := st.Name
|
name := st.Name
|
||||||
if d, ok := m[name]; ok {
|
if d, ok := m[name]; ok {
|
||||||
|
|||||||
136
vendor/github.com/osrg/gobgp/table/table.go
generated
vendored
136
vendor/github.com/osrg/gobgp/table/table.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/armon/go-radix"
|
"github.com/armon/go-radix"
|
||||||
"github.com/osrg/gobgp/packet/bgp"
|
"github.com/osrg/gobgp/packet/bgp"
|
||||||
@ -41,6 +42,7 @@ type LookupPrefix struct {
|
|||||||
|
|
||||||
type TableSelectOption struct {
|
type TableSelectOption struct {
|
||||||
ID string
|
ID string
|
||||||
|
AS uint32
|
||||||
LookupPrefixes []*LookupPrefix
|
LookupPrefixes []*LookupPrefix
|
||||||
VRF *Vrf
|
VRF *Vrf
|
||||||
adj bool
|
adj bool
|
||||||
@ -54,51 +56,20 @@ type Table struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table {
|
func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table {
|
||||||
destinations := make(map[string]*Destination)
|
t := &Table{
|
||||||
for _, dst := range dsts {
|
|
||||||
destinations[dst.GetNlri().String()] = dst
|
|
||||||
}
|
|
||||||
return &Table{
|
|
||||||
routeFamily: rf,
|
routeFamily: rf,
|
||||||
destinations: destinations,
|
destinations: make(map[string]*Destination),
|
||||||
}
|
}
|
||||||
|
for _, dst := range dsts {
|
||||||
|
t.setDestination(dst)
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) GetRoutefamily() bgp.RouteFamily {
|
func (t *Table) GetRoutefamily() bgp.RouteFamily {
|
||||||
return t.routeFamily
|
return t.routeFamily
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) insert(path *Path) *Destination {
|
|
||||||
t.validatePath(path)
|
|
||||||
dest := t.getOrCreateDest(path.GetNlri())
|
|
||||||
|
|
||||||
if path.IsWithdraw {
|
|
||||||
// withdraw insert
|
|
||||||
dest.AddWithdraw(path)
|
|
||||||
} else {
|
|
||||||
// path insert
|
|
||||||
dest.AddNewPath(path)
|
|
||||||
}
|
|
||||||
return dest
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) DeleteDestByPeer(peerInfo *PeerInfo) []*Destination {
|
|
||||||
dsts := []*Destination{}
|
|
||||||
for _, dst := range t.destinations {
|
|
||||||
match := false
|
|
||||||
for _, p := range dst.knownPathList {
|
|
||||||
if p.GetSource().Equal(peerInfo) {
|
|
||||||
dst.AddWithdraw(p)
|
|
||||||
match = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if match {
|
|
||||||
dsts = append(dsts, dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dsts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
|
func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
|
||||||
pathList := make([]*Path, 0)
|
pathList := make([]*Path, 0)
|
||||||
for _, dest := range t.destinations {
|
for _, dest := range t.destinations {
|
||||||
@ -148,15 +119,11 @@ func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
|
func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
|
||||||
destinations := t.GetDestinations()
|
if dst := t.GetDestination(nlri); dst != nil {
|
||||||
dest := destinations[t.tableKey(nlri)]
|
t.deleteDest(dst)
|
||||||
if dest != nil {
|
return dst
|
||||||
delete(destinations, t.tableKey(nlri))
|
|
||||||
if len(destinations) == 0 {
|
|
||||||
t.destinations = make(map[string]*Destination)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return dest
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) deleteDest(dest *Destination) {
|
func (t *Table) deleteDest(dest *Destination) {
|
||||||
@ -210,16 +177,15 @@ func (t *Table) validatePath(path *Path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
|
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
|
||||||
tableKey := t.tableKey(nlri)
|
dest := t.GetDestination(nlri)
|
||||||
dest := t.GetDestination(tableKey)
|
|
||||||
// If destination for given prefix does not exist we create it.
|
// If destination for given prefix does not exist we create it.
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Table",
|
"Topic": "Table",
|
||||||
"Key": tableKey,
|
"Nlri": nlri,
|
||||||
}).Debugf("create Destination")
|
}).Debugf("create Destination")
|
||||||
dest = NewDestination(nlri, 64)
|
dest = NewDestination(nlri, 64)
|
||||||
t.setDestination(tableKey, dest)
|
t.setDestination(dest)
|
||||||
}
|
}
|
||||||
return dest
|
return dest
|
||||||
}
|
}
|
||||||
@ -230,7 +196,7 @@ func (t *Table) GetSortedDestinations() []*Destination {
|
|||||||
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC:
|
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC:
|
||||||
r := radix.New()
|
r := radix.New()
|
||||||
for _, dst := range t.GetDestinations() {
|
for _, dst := range t.GetDestinations() {
|
||||||
r.Insert(dst.RadixKey, dst)
|
r.Insert(AddrToRadixkey(dst.nlri), dst)
|
||||||
}
|
}
|
||||||
r.Walk(func(s string, v interface{}) bool {
|
r.Walk(func(s string, v interface{}) bool {
|
||||||
results = append(results, v.(*Destination))
|
results = append(results, v.(*Destination))
|
||||||
@ -251,8 +217,8 @@ func (t *Table) GetDestinations() map[string]*Destination {
|
|||||||
func (t *Table) setDestinations(destinations map[string]*Destination) {
|
func (t *Table) setDestinations(destinations map[string]*Destination) {
|
||||||
t.destinations = destinations
|
t.destinations = destinations
|
||||||
}
|
}
|
||||||
func (t *Table) GetDestination(key string) *Destination {
|
func (t *Table) GetDestination(nlri bgp.AddrPrefixInterface) *Destination {
|
||||||
dest, ok := t.destinations[key]
|
dest, ok := t.destinations[t.tableKey(nlri)]
|
||||||
if ok {
|
if ok {
|
||||||
return dest
|
return dest
|
||||||
} else {
|
} else {
|
||||||
@ -271,7 +237,7 @@ func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error)
|
|||||||
k := CidrToRadixkey(prefix.String())
|
k := CidrToRadixkey(prefix.String())
|
||||||
r := radix.New()
|
r := radix.New()
|
||||||
for _, dst := range t.GetDestinations() {
|
for _, dst := range t.GetDestinations() {
|
||||||
r.Insert(dst.RadixKey, dst)
|
r.Insert(AddrToRadixkey(dst.nlri), dst)
|
||||||
}
|
}
|
||||||
r.WalkPrefix(k, func(s string, v interface{}) bool {
|
r.WalkPrefix(k, func(s string, v interface{}) bool {
|
||||||
results = append(results, v.(*Destination))
|
results = append(results, v.(*Destination))
|
||||||
@ -320,18 +286,30 @@ func (t *Table) GetEvpnDestinationsWithRouteType(typ string) ([]*Destination, er
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) setDestination(key string, dest *Destination) {
|
func (t *Table) setDestination(dst *Destination) {
|
||||||
t.destinations[key] = dest
|
t.destinations[t.tableKey(dst.nlri)] = dst
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string {
|
func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string {
|
||||||
|
switch T := nlri.(type) {
|
||||||
|
case *bgp.IPAddrPrefix:
|
||||||
|
b := make([]byte, 5)
|
||||||
|
copy(b, T.Prefix.To4())
|
||||||
|
b[4] = T.Length
|
||||||
|
return *(*string)(unsafe.Pointer(&b))
|
||||||
|
case *bgp.IPv6AddrPrefix:
|
||||||
|
b := make([]byte, 17)
|
||||||
|
copy(b, T.Prefix.To16())
|
||||||
|
b[16] = T.Length
|
||||||
|
return *(*string)(unsafe.Pointer(&b))
|
||||||
|
}
|
||||||
return nlri.String()
|
return nlri.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) Bests(id string) []*Path {
|
func (t *Table) Bests(id string, as uint32) []*Path {
|
||||||
paths := make([]*Path, 0, len(t.destinations))
|
paths := make([]*Path, 0, len(t.destinations))
|
||||||
for _, dst := range t.destinations {
|
for _, dst := range t.destinations {
|
||||||
path := dst.GetBestPath(id)
|
path := dst.GetBestPath(id, as)
|
||||||
if path != nil {
|
if path != nil {
|
||||||
paths = append(paths, path)
|
paths = append(paths, path)
|
||||||
}
|
}
|
||||||
@ -350,10 +328,10 @@ func (t *Table) MultiBests(id string) [][]*Path {
|
|||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) GetKnownPathList(id string) []*Path {
|
func (t *Table) GetKnownPathList(id string, as uint32) []*Path {
|
||||||
paths := make([]*Path, 0, len(t.destinations))
|
paths := make([]*Path, 0, len(t.destinations))
|
||||||
for _, dst := range t.destinations {
|
for _, dst := range t.destinations {
|
||||||
paths = append(paths, dst.GetKnownPathList(id)...)
|
paths = append(paths, dst.GetKnownPathList(id, as)...)
|
||||||
}
|
}
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
@ -365,6 +343,7 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
|||||||
prefixes := make([]*LookupPrefix, 0, len(option))
|
prefixes := make([]*LookupPrefix, 0, len(option))
|
||||||
best := false
|
best := false
|
||||||
mp := false
|
mp := false
|
||||||
|
as := uint32(0)
|
||||||
for _, o := range option {
|
for _, o := range option {
|
||||||
if o.ID != "" {
|
if o.ID != "" {
|
||||||
id = o.ID
|
id = o.ID
|
||||||
@ -376,17 +355,27 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
|||||||
prefixes = append(prefixes, o.LookupPrefixes...)
|
prefixes = append(prefixes, o.LookupPrefixes...)
|
||||||
best = o.Best
|
best = o.Best
|
||||||
mp = o.MultiPath
|
mp = o.MultiPath
|
||||||
|
as = o.AS
|
||||||
|
}
|
||||||
|
dOption := DestinationSelectOption{ID: id, AS: as, VRF: vrf, adj: adj, Best: best, MultiPath: mp}
|
||||||
|
r := &Table{
|
||||||
|
routeFamily: t.routeFamily,
|
||||||
|
destinations: make(map[string]*Destination),
|
||||||
}
|
}
|
||||||
dOption := DestinationSelectOption{ID: id, VRF: vrf, adj: adj, Best: best, MultiPath: mp}
|
|
||||||
dsts := make(map[string]*Destination)
|
|
||||||
|
|
||||||
if len(prefixes) != 0 {
|
if len(prefixes) != 0 {
|
||||||
switch t.routeFamily {
|
switch t.routeFamily {
|
||||||
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS:
|
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC:
|
||||||
f := func(key string) bool {
|
f := func(prefixStr string) bool {
|
||||||
if dst := t.GetDestination(key); dst != nil {
|
var nlri bgp.AddrPrefixInterface
|
||||||
|
if t.routeFamily == bgp.RF_IPv4_UC {
|
||||||
|
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, prefixStr)
|
||||||
|
} else {
|
||||||
|
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, prefixStr)
|
||||||
|
}
|
||||||
|
if dst := t.GetDestination(nlri); dst != nil {
|
||||||
if d := dst.Select(dOption); d != nil {
|
if d := dst.Select(dOption); d != nil {
|
||||||
dsts[key] = d
|
r.setDestination(d)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,7 +392,7 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
|||||||
}
|
}
|
||||||
for _, dst := range ds {
|
for _, dst := range ds {
|
||||||
if d := dst.Select(dOption); d != nil {
|
if d := dst.Select(dOption); d != nil {
|
||||||
dsts[dst.GetNlri().String()] = d
|
r.setDestination(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case LOOKUP_SHORTER:
|
case LOOKUP_SHORTER:
|
||||||
@ -445,7 +434,7 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
|||||||
}
|
}
|
||||||
for _, dst := range ds {
|
for _, dst := range ds {
|
||||||
if d := dst.Select(dOption); d != nil {
|
if d := dst.Select(dOption); d != nil {
|
||||||
dsts[dst.GetNlri().String()] = d
|
r.setDestination(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -453,16 +442,13 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
|||||||
return nil, fmt.Errorf("route filtering is not supported for this family")
|
return nil, fmt.Errorf("route filtering is not supported for this family")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for k, dst := range t.GetDestinations() {
|
for _, dst := range t.GetDestinations() {
|
||||||
if d := dst.Select(dOption); d != nil {
|
if d := dst.Select(dOption); d != nil {
|
||||||
dsts[k] = d
|
r.setDestination(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Table{
|
return r, nil
|
||||||
routeFamily: t.routeFamily,
|
|
||||||
destinations: dsts,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TableInfo struct {
|
type TableInfo struct {
|
||||||
@ -471,10 +457,10 @@ type TableInfo struct {
|
|||||||
NumAccepted int
|
NumAccepted int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) Info(id string) *TableInfo {
|
func (t *Table) Info(id string, as uint32) *TableInfo {
|
||||||
var numD, numP int
|
var numD, numP int
|
||||||
for _, d := range t.destinations {
|
for _, d := range t.destinations {
|
||||||
ps := d.GetKnownPathList(id)
|
ps := d.GetKnownPathList(id, as)
|
||||||
if len(ps) > 0 {
|
if len(ps) > 0 {
|
||||||
numD += 1
|
numD += 1
|
||||||
numP += len(ps)
|
numP += len(ps)
|
||||||
|
|||||||
111
vendor/github.com/osrg/gobgp/table/table_manager.go
generated
vendored
111
vendor/github.com/osrg/gobgp/table/table_manager.go
generated
vendored
@ -57,9 +57,7 @@ func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time)
|
|||||||
reach = a
|
reach = a
|
||||||
case *bgp.PathAttributeMpUnreachNLRI:
|
case *bgp.PathAttributeMpUnreachNLRI:
|
||||||
l := make([]bgp.AddrPrefixInterface, 0, len(a.Value))
|
l := make([]bgp.AddrPrefixInterface, 0, len(a.Value))
|
||||||
for _, nlri := range a.Value {
|
l = append(l, a.Value...)
|
||||||
l = append(l, nlri)
|
|
||||||
}
|
|
||||||
dels = append(dels, l...)
|
dels = append(dels, l...)
|
||||||
default:
|
default:
|
||||||
attrs = append(attrs, attr)
|
attrs = append(attrs, attr)
|
||||||
@ -180,65 +178,50 @@ func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) {
|
|||||||
return msgs, nil
|
return msgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) calculate(dsts []*Destination) []*Destination {
|
func (tm *TableManager) update(newPath *Path) *Update {
|
||||||
emptyDsts := make([]*Destination, 0, len(dsts))
|
t := tm.Tables[newPath.GetRouteFamily()]
|
||||||
clonedDsts := make([]*Destination, 0, len(dsts))
|
t.validatePath(newPath)
|
||||||
|
dst := t.getOrCreateDest(newPath.GetNlri())
|
||||||
for _, dst := range dsts {
|
u := dst.Calculate(newPath)
|
||||||
log.WithFields(log.Fields{
|
if len(dst.knownPathList) == 0 {
|
||||||
"Topic": "table",
|
|
||||||
"Key": dst.GetNlri().String(),
|
|
||||||
}).Debug("Processing destination")
|
|
||||||
|
|
||||||
clonedDsts = append(clonedDsts, dst.Calculate())
|
|
||||||
|
|
||||||
if len(dst.knownPathList) == 0 {
|
|
||||||
emptyDsts = append(emptyDsts, dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dst := range emptyDsts {
|
|
||||||
t := manager.Tables[dst.Family()]
|
|
||||||
t.deleteDest(dst)
|
t.deleteDest(dst)
|
||||||
}
|
}
|
||||||
return clonedDsts
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) DeletePathsByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Destination {
|
func (manager *TableManager) GetPathListByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Path {
|
||||||
if t, ok := manager.Tables[rf]; ok {
|
if t, ok := manager.Tables[rf]; ok {
|
||||||
dsts := t.DeleteDestByPeer(info)
|
pathList := make([]*Path, 0, len(t.destinations))
|
||||||
return manager.calculate(dsts)
|
for _, dst := range t.destinations {
|
||||||
|
for _, p := range dst.knownPathList {
|
||||||
|
if p.GetSource().Equal(info) {
|
||||||
|
pathList = append(pathList, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pathList
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) ProcessPaths(pathList []*Path) []*Destination {
|
func (manager *TableManager) Update(newPath *Path) []*Update {
|
||||||
m := make(map[string]bool, len(pathList))
|
if newPath == nil || newPath.IsEOR() {
|
||||||
dsts := make([]*Destination, 0, len(pathList))
|
return nil
|
||||||
for _, path := range pathList {
|
}
|
||||||
if path == nil || path.IsEOR() {
|
|
||||||
continue
|
// Except for a special case with EVPN, we'll have one destination.
|
||||||
}
|
updates := make([]*Update, 0, 1)
|
||||||
rf := path.GetRouteFamily()
|
family := newPath.GetRouteFamily()
|
||||||
if t, ok := manager.Tables[rf]; ok {
|
if _, ok := manager.Tables[family]; ok {
|
||||||
dst := t.insert(path)
|
updates = append(updates, manager.update(newPath))
|
||||||
key := dst.GetNlri().String()
|
|
||||||
if !m[key] {
|
if family == bgp.RF_EVPN {
|
||||||
m[key] = true
|
for _, p := range manager.handleMacMobility(newPath) {
|
||||||
dsts = append(dsts, dst)
|
updates = append(updates, manager.update(p))
|
||||||
}
|
|
||||||
if rf == bgp.RF_EVPN {
|
|
||||||
for _, dst := range manager.handleMacMobility(path) {
|
|
||||||
key := dst.GetNlri().String()
|
|
||||||
if !m[key] {
|
|
||||||
m[key] = true
|
|
||||||
dsts = append(dsts, dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return manager.calculate(dsts)
|
return updates
|
||||||
}
|
}
|
||||||
|
|
||||||
// EVPN MAC MOBILITY HANDLING
|
// EVPN MAC MOBILITY HANDLING
|
||||||
@ -249,13 +232,13 @@ func (manager *TableManager) ProcessPaths(pathList []*Path) []*Destination {
|
|||||||
// different Ethernet segment identifier and a higher sequence number
|
// different Ethernet segment identifier and a higher sequence number
|
||||||
// than that which it had previously advertised withdraws its MAC/IP
|
// than that which it had previously advertised withdraws its MAC/IP
|
||||||
// Advertisement route.
|
// Advertisement route.
|
||||||
func (manager *TableManager) handleMacMobility(path *Path) []*Destination {
|
func (manager *TableManager) handleMacMobility(path *Path) []*Path {
|
||||||
dsts := make([]*Destination, 0)
|
pathList := make([]*Path, 0)
|
||||||
nlri := path.GetNlri().(*bgp.EVPNNLRI)
|
nlri := path.GetNlri().(*bgp.EVPNNLRI)
|
||||||
if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, []bgp.RouteFamily{bgp.RF_EVPN}) {
|
for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, 0, []bgp.RouteFamily{bgp.RF_EVPN}) {
|
||||||
if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -275,12 +258,10 @@ func (manager *TableManager) handleMacMobility(path *Path) []*Destination {
|
|||||||
e1, m1, s1 := f(path)
|
e1, m1, s1 := f(path)
|
||||||
e2, m2, s2 := f(path2)
|
e2, m2, s2 := f(path2)
|
||||||
if bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) && s1 > s2 {
|
if bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) && s1 > s2 {
|
||||||
path2.IsWithdraw = true
|
pathList = append(pathList, path2.Clone(true))
|
||||||
dsts = append(dsts, manager.Tables[bgp.RF_EVPN].insert(path2))
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dsts
|
return pathList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table {
|
func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table {
|
||||||
@ -307,14 +288,14 @@ func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) GetBestPathList(id string, rfList []bgp.RouteFamily) []*Path {
|
func (manager *TableManager) GetBestPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
|
||||||
if SelectionOptions.DisableBestPathSelection {
|
if SelectionOptions.DisableBestPathSelection {
|
||||||
// Note: If best path selection disabled, there is no best path.
|
// Note: If best path selection disabled, there is no best path.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||||
for _, t := range manager.tables(rfList...) {
|
for _, t := range manager.tables(rfList...) {
|
||||||
paths = append(paths, t.Bests(id)...)
|
paths = append(paths, t.Bests(id, as)...)
|
||||||
}
|
}
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
@ -332,10 +313,10 @@ func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteF
|
|||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) GetPathList(id string, rfList []bgp.RouteFamily) []*Path {
|
func (manager *TableManager) GetPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
|
||||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||||
for _, t := range manager.tables(rfList...) {
|
for _, t := range manager.tables(rfList...) {
|
||||||
paths = append(paths, t.GetKnownPathList(id)...)
|
paths = append(paths, t.GetKnownPathList(id, as)...)
|
||||||
}
|
}
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
@ -344,7 +325,7 @@ func (manager *TableManager) GetPathListWithNexthop(id string, rfList []bgp.Rout
|
|||||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||||
for _, rf := range rfList {
|
for _, rf := range rfList {
|
||||||
if t, ok := manager.Tables[rf]; ok {
|
if t, ok := manager.Tables[rf]; ok {
|
||||||
for _, path := range t.GetKnownPathList(id) {
|
for _, path := range t.GetKnownPathList(id, 0) {
|
||||||
if path.GetNexthop().Equal(nexthop) {
|
if path.GetNexthop().Equal(nexthop) {
|
||||||
paths = append(paths, path)
|
paths = append(paths, path)
|
||||||
}
|
}
|
||||||
@ -363,13 +344,13 @@ func (manager *TableManager) GetDestination(path *Path) *Destination {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return t.GetDestination(path.getPrefix())
|
return t.GetDestination(path.GetNlri())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *TableManager) TableInfo(id string, family bgp.RouteFamily) (*TableInfo, error) {
|
func (manager *TableManager) TableInfo(id string, as uint32, family bgp.RouteFamily) (*TableInfo, error) {
|
||||||
t, ok := manager.Tables[family]
|
t, ok := manager.Tables[family]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("address family %s is not configured", family)
|
return nil, fmt.Errorf("address family %s is not configured", family)
|
||||||
}
|
}
|
||||||
return t.Info(id), nil
|
return t.Info(id, as), nil
|
||||||
}
|
}
|
||||||
|
|||||||
5
vendor/github.com/osrg/gobgp/table/vrf.go
generated
vendored
5
vendor/github.com/osrg/gobgp/table/vrf.go
generated
vendored
@ -30,10 +30,7 @@ type Vrf struct {
|
|||||||
func (v *Vrf) Clone() *Vrf {
|
func (v *Vrf) Clone() *Vrf {
|
||||||
f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface {
|
f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface {
|
||||||
l := make([]bgp.ExtendedCommunityInterface, 0, len(rt))
|
l := make([]bgp.ExtendedCommunityInterface, 0, len(rt))
|
||||||
for _, v := range rt {
|
return append(l, rt...)
|
||||||
l = append(l, v)
|
|
||||||
}
|
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
return &Vrf{
|
return &Vrf{
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
|
|||||||
110
vendor/github.com/osrg/gobgp/zebra/zapi.go
generated
vendored
110
vendor/github.com/osrg/gobgp/zebra/zapi.go
generated
vendored
@ -546,7 +546,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Zebra",
|
"Topic": "Zebra",
|
||||||
}).Warnf("failed to serialize: %s", m)
|
}).Warnf("failed to serialize: %v", m)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,43 +571,51 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client,
|
|||||||
receiveSingleMsg := func() (*Message, error) {
|
receiveSingleMsg := func() (*Message, error) {
|
||||||
headerBuf, err := readAll(conn, int(HeaderSize(version)))
|
headerBuf, err := readAll(conn, int(HeaderSize(version)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("failed to read header: %s", err)
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Zebra",
|
"Topic": "Zebra",
|
||||||
}).Error(err)
|
"Error": err,
|
||||||
|
}).Error("failed to read header")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
}).Debugf("read header from zebra: %v", headerBuf)
|
|
||||||
hd := &Header{}
|
hd := &Header{}
|
||||||
err = hd.DecodeFromBytes(headerBuf)
|
err = hd.DecodeFromBytes(headerBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("failed to decode header: %s", err)
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Zebra",
|
"Topic": "Zebra",
|
||||||
}).Error(err)
|
"Data": headerBuf,
|
||||||
|
"Error": err,
|
||||||
|
}).Error("failed to decode header")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyBuf, err := readAll(conn, int(hd.Len-HeaderSize(version)))
|
bodyBuf, err := readAll(conn, int(hd.Len-HeaderSize(version)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("failed to read body: %s", err)
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Zebra",
|
"Topic": "Zebra",
|
||||||
}).Error(err)
|
"Header": hd,
|
||||||
|
"Error": err,
|
||||||
|
}).Error("failed to read body")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Topic": "Zebra",
|
|
||||||
}).Debugf("read body from zebra: %v", bodyBuf)
|
|
||||||
m, err := ParseMessage(hd, bodyBuf)
|
m, err := ParseMessage(hd, bodyBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Just outputting warnings (not error message) and ignore this
|
||||||
|
// error considering the case that body parser is not implemented
|
||||||
|
// yet.
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Topic": "Zebra",
|
"Topic": "Zebra",
|
||||||
}).Warnf("failed to parse message: %s", err)
|
"Header": hd,
|
||||||
|
"Data": bodyBuf,
|
||||||
|
"Error": err,
|
||||||
|
}).Warn("failed to decode body")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Topic": "Zebra",
|
||||||
|
"Message": m,
|
||||||
|
}).Debug("read message from zebra")
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@ -623,6 +631,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client,
|
|||||||
|
|
||||||
// Start receive loop only when the first message successfully received.
|
// Start receive loop only when the first message successfully received.
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(incoming)
|
||||||
for {
|
for {
|
||||||
if m, err := receiveSingleMsg(); err != nil {
|
if m, err := receiveSingleMsg(); err != nil {
|
||||||
return
|
return
|
||||||
@ -898,7 +907,7 @@ func (b *HelloBody) Serialize(version uint8) ([]byte, error) {
|
|||||||
if version <= 3 {
|
if version <= 3 {
|
||||||
return []byte{uint8(b.RedistDefault)}, nil
|
return []byte{uint8(b.RedistDefault)}, nil
|
||||||
} else { // version >= 4
|
} else { // version >= 4
|
||||||
buf := make([]byte, 3, 3)
|
buf := make([]byte, 3)
|
||||||
buf[0] = uint8(b.RedistDefault)
|
buf[0] = uint8(b.RedistDefault)
|
||||||
binary.BigEndian.PutUint16(buf[1:3], b.Instance)
|
binary.BigEndian.PutUint16(buf[1:3], b.Instance)
|
||||||
return buf, nil
|
return buf, nil
|
||||||
@ -933,7 +942,7 @@ func (b *RedistributeBody) Serialize(version uint8) ([]byte, error) {
|
|||||||
if version <= 3 {
|
if version <= 3 {
|
||||||
return []byte{uint8(b.Redist)}, nil
|
return []byte{uint8(b.Redist)}, nil
|
||||||
} else { // version >= 4
|
} else { // version >= 4
|
||||||
buf := make([]byte, 4, 4)
|
buf := make([]byte, 4)
|
||||||
buf[0] = uint8(b.Afi)
|
buf[0] = uint8(b.Afi)
|
||||||
buf[1] = uint8(b.Redist)
|
buf[1] = uint8(b.Redist)
|
||||||
binary.BigEndian.PutUint16(buf[2:4], b.Instance)
|
binary.BigEndian.PutUint16(buf[2:4], b.Instance)
|
||||||
@ -1398,71 +1407,6 @@ func (n *Nexthop) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func serializeNexthops(nexthops []*Nexthop, isV4 bool, version uint8) ([]byte, error) {
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
if len(nexthops) == 0 {
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
||||||
buf = append(buf, byte(len(nexthops)))
|
|
||||||
|
|
||||||
nhIfindex := NEXTHOP_IFINDEX
|
|
||||||
nhIfname := NEXTHOP_IFNAME
|
|
||||||
nhIPv4 := NEXTHOP_IPV4
|
|
||||||
nhIPv4Ifindex := NEXTHOP_IPV4_IFINDEX
|
|
||||||
nhIPv4Ifname := NEXTHOP_IPV4_IFNAME
|
|
||||||
nhIPv6 := NEXTHOP_IPV6
|
|
||||||
nhIPv6Ifindex := NEXTHOP_IPV6_IFINDEX
|
|
||||||
nhIPv6Ifname := NEXTHOP_IPV6_IFNAME
|
|
||||||
if version >= 4 {
|
|
||||||
nhIfindex = FRR_NEXTHOP_IFINDEX
|
|
||||||
nhIfname = NEXTHOP_FLAG(0)
|
|
||||||
nhIPv4 = FRR_NEXTHOP_IPV4
|
|
||||||
nhIPv4Ifindex = FRR_NEXTHOP_IPV4_IFINDEX
|
|
||||||
nhIPv4Ifname = NEXTHOP_FLAG(0)
|
|
||||||
nhIPv6 = FRR_NEXTHOP_IPV6
|
|
||||||
nhIPv6Ifindex = FRR_NEXTHOP_IPV6_IFINDEX
|
|
||||||
nhIPv6Ifname = NEXTHOP_FLAG(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, nh := range nexthops {
|
|
||||||
buf = append(buf, byte(nh.Type))
|
|
||||||
|
|
||||||
switch nh.Type {
|
|
||||||
case nhIfindex, nhIfname:
|
|
||||||
bbuf := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(bbuf, nh.Ifindex)
|
|
||||||
buf = append(buf, bbuf...)
|
|
||||||
|
|
||||||
case nhIPv4, nhIPv6:
|
|
||||||
if isV4 {
|
|
||||||
buf = append(buf, nh.Addr.To4()...)
|
|
||||||
} else {
|
|
||||||
buf = append(buf, nh.Addr.To16()...)
|
|
||||||
}
|
|
||||||
if version >= 4 {
|
|
||||||
// On FRRouting version 3.0 or later, NEXTHOP_IPV4 and
|
|
||||||
// NEXTHOP_IPV6 have the same structure with
|
|
||||||
// NEXTHOP_TYPE_IPV4_IFINDEX and NEXTHOP_TYPE_IPV6_IFINDEX.
|
|
||||||
bbuf := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(bbuf, nh.Ifindex)
|
|
||||||
buf = append(buf, bbuf...)
|
|
||||||
}
|
|
||||||
|
|
||||||
case nhIPv4Ifindex, nhIPv4Ifname, nhIPv6Ifindex, nhIPv6Ifname:
|
|
||||||
if isV4 {
|
|
||||||
buf = append(buf, nh.Addr.To4()...)
|
|
||||||
} else {
|
|
||||||
buf = append(buf, nh.Addr.To16()...)
|
|
||||||
}
|
|
||||||
bbuf := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(bbuf, nh.Ifindex)
|
|
||||||
buf = append(buf, bbuf...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeNexthopsFromBytes(nexthops *[]*Nexthop, data []byte, isV4 bool, version uint8) (int, error) {
|
func decodeNexthopsFromBytes(nexthops *[]*Nexthop, data []byte, isV4 bool, version uint8) (int, error) {
|
||||||
addrLen := net.IPv4len
|
addrLen := net.IPv4len
|
||||||
if !isV4 {
|
if !isV4 {
|
||||||
|
|||||||
683
vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go
generated
vendored
683
vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go
generated
vendored
@ -1,683 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
func initAgpl() {
|
|
||||||
Licenses["agpl"] = License{
|
|
||||||
Name: "GNU Affero General Public License",
|
|
||||||
PossibleMatches: []string{"agpl", "affero gpl", "gnu agpl"},
|
|
||||||
Header: `
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.`,
|
|
||||||
Text: ` GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 19 November 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works, specifically designed to ensure
|
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
|
||||||
you this License which gives you legal permission to copy, distribute
|
|
||||||
and/or modify the software.
|
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
|
||||||
improvements made in alternate versions of the program, if they
|
|
||||||
receive widespread use, become available for other developers to
|
|
||||||
incorporate. Many developers of free software are heartened and
|
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
|
||||||
ensure that, in such cases, the modified source code becomes available
|
|
||||||
to the community. It requires the operator of a network server to
|
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
|
||||||
this license.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the work with which it is combined will remain governed by version
|
|
||||||
3 of the GNU General Public License.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
|
||||||
network, you should also make sure that it provides a way for users to
|
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
|
||||||
of the code. There are many ways you could offer source, and different
|
|
||||||
solutions will be better for different programs; see section 13 for the
|
|
||||||
specific requirements.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
238
vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go
generated
vendored
238
vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go
generated
vendored
@ -1,238 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initApache2() {
|
|
||||||
Licenses["apache"] = License{
|
|
||||||
Name: "Apache 2.0",
|
|
||||||
PossibleMatches: []string{"apache", "apache20", "apache 2.0", "apache2.0", "apache-2.0"},
|
|
||||||
Header: `
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.`,
|
|
||||||
Text: `
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
71
vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go
generated
vendored
71
vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initBsdClause2() {
|
|
||||||
Licenses["freebsd"] = License{
|
|
||||||
Name: "Simplified BSD License",
|
|
||||||
PossibleMatches: []string{"freebsd", "simpbsd", "simple bsd", "2-clause bsd",
|
|
||||||
"2 clause bsd", "simplified bsd license"},
|
|
||||||
Header: `All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.`,
|
|
||||||
Text: `{{ .copyright }}
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
78
vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go
generated
vendored
78
vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go
generated
vendored
@ -1,78 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initBsdClause3() {
|
|
||||||
Licenses["bsd"] = License{
|
|
||||||
Name: "NewBSD",
|
|
||||||
PossibleMatches: []string{"bsd", "newbsd", "3 clause bsd", "3-clause bsd"},
|
|
||||||
Header: `All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.`,
|
|
||||||
Text: `{{ .copyright }}
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
376
vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go
generated
vendored
376
vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go
generated
vendored
@ -1,376 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initGpl2() {
|
|
||||||
Licenses["gpl2"] = License{
|
|
||||||
Name: "GNU General Public License 2.0",
|
|
||||||
PossibleMatches: []string{"gpl2", "gnu gpl2", "gplv2"},
|
|
||||||
Header: `
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.`,
|
|
||||||
Text: ` GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type 'show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands 'show w' and 'show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than 'show w' and 'show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
'Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
711
vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go
generated
vendored
711
vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go
generated
vendored
@ -1,711 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initGpl3() {
|
|
||||||
Licenses["gpl3"] = License{
|
|
||||||
Name: "GNU General Public License 3.0",
|
|
||||||
PossibleMatches: []string{"gpl3", "gplv3", "gpl", "gnu gpl3", "gnu gpl"},
|
|
||||||
Header: `
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.`,
|
|
||||||
Text: ` GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type 'show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands 'show w' and 'show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
186
vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go
generated
vendored
186
vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go
generated
vendored
@ -1,186 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
func initLgpl() {
|
|
||||||
Licenses["lgpl"] = License{
|
|
||||||
Name: "GNU Lesser General Public License",
|
|
||||||
PossibleMatches: []string{"lgpl", "lesser gpl", "gnu lgpl"},
|
|
||||||
Header: `
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.`,
|
|
||||||
Text: ` GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
63
vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go
generated
vendored
63
vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go
generated
vendored
@ -1,63 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
func initMit() {
|
|
||||||
Licenses["mit"] = License{
|
|
||||||
Name: "MIT License",
|
|
||||||
PossibleMatches: []string{"mit"},
|
|
||||||
Header: `
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.`,
|
|
||||||
Text: `The MIT License (MIT)
|
|
||||||
|
|
||||||
{{ .copyright }}
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
118
vendor/github.com/spf13/cobra/cobra/cmd/licenses.go
generated
vendored
118
vendor/github.com/spf13/cobra/cobra/cmd/licenses.go
generated
vendored
@ -1,118 +0,0 @@
|
|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Parts inspired by https://github.com/ryanuber/go-license
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Licenses contains all possible licenses a user can choose from.
|
|
||||||
var Licenses = make(map[string]License)
|
|
||||||
|
|
||||||
// License represents a software license agreement, containing the Name of
|
|
||||||
// the license, its possible matches (on the command line as given to cobra),
|
|
||||||
// the header to be used with each file on the file's creating, and the text
|
|
||||||
// of the license
|
|
||||||
type License struct {
|
|
||||||
Name string // The type of license in use
|
|
||||||
PossibleMatches []string // Similar names to guess
|
|
||||||
Text string // License text data
|
|
||||||
Header string // License header for source files
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Allows a user to not use a license.
|
|
||||||
Licenses["none"] = License{"None", []string{"none", "false"}, "", ""}
|
|
||||||
|
|
||||||
initApache2()
|
|
||||||
initMit()
|
|
||||||
initBsdClause3()
|
|
||||||
initBsdClause2()
|
|
||||||
initGpl2()
|
|
||||||
initGpl3()
|
|
||||||
initLgpl()
|
|
||||||
initAgpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
// getLicense returns license specified by user in flag or in config.
|
|
||||||
// If user didn't specify the license, it returns Apache License 2.0.
|
|
||||||
//
|
|
||||||
// TODO: Inspect project for existing license
|
|
||||||
func getLicense() License {
|
|
||||||
// If explicitly flagged, use that.
|
|
||||||
if userLicense != "" {
|
|
||||||
return findLicense(userLicense)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user wants to have custom license, use that.
|
|
||||||
if viper.IsSet("license.header") || viper.IsSet("license.text") {
|
|
||||||
return License{Header: viper.GetString("license.header"),
|
|
||||||
Text: viper.GetString("license.text")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user wants to have built-in license, use that.
|
|
||||||
if viper.IsSet("license") {
|
|
||||||
return findLicense(viper.GetString("license"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user didn't set any license, use Apache 2.0 by default.
|
|
||||||
return Licenses["apache"]
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyrightLine() string {
|
|
||||||
author := viper.GetString("author")
|
|
||||||
|
|
||||||
year := viper.GetString("year") // For tests.
|
|
||||||
if year == "" {
|
|
||||||
year = time.Now().Format("2006")
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Copyright © " + year + " " + author
|
|
||||||
}
|
|
||||||
|
|
||||||
// findLicense looks for License object of built-in licenses.
|
|
||||||
// If it didn't find license, then the app will be terminated and
|
|
||||||
// error will be printed.
|
|
||||||
func findLicense(name string) License {
|
|
||||||
found := matchLicense(name)
|
|
||||||
if found == "" {
|
|
||||||
er("unknown license: " + name)
|
|
||||||
}
|
|
||||||
return Licenses[found]
|
|
||||||
}
|
|
||||||
|
|
||||||
// matchLicense compares the given a license name
|
|
||||||
// to PossibleMatches of all built-in licenses.
|
|
||||||
// It returns blank string, if name is blank string or it didn't find
|
|
||||||
// then appropriate match to name.
|
|
||||||
func matchLicense(name string) string {
|
|
||||||
if name == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, lic := range Licenses {
|
|
||||||
for _, match := range lic.PossibleMatches {
|
|
||||||
if strings.EqualFold(name, match) {
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package pflag
|
package pflag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@ -9,10 +10,12 @@ import (
|
|||||||
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
||||||
type bytesHexValue []byte
|
type bytesHexValue []byte
|
||||||
|
|
||||||
|
// String implements pflag.Value.String.
|
||||||
func (bytesHex bytesHexValue) String() string {
|
func (bytesHex bytesHexValue) String() string {
|
||||||
return fmt.Sprintf("%X", []byte(bytesHex))
|
return fmt.Sprintf("%X", []byte(bytesHex))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set implements pflag.Value.Set.
|
||||||
func (bytesHex *bytesHexValue) Set(value string) error {
|
func (bytesHex *bytesHexValue) Set(value string) error {
|
||||||
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
||||||
|
|
||||||
@ -25,6 +28,7 @@ func (bytesHex *bytesHexValue) Set(value string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type implements pflag.Value.Type.
|
||||||
func (*bytesHexValue) Type() string {
|
func (*bytesHexValue) Type() string {
|
||||||
return "bytesHex"
|
return "bytesHex"
|
||||||
}
|
}
|
||||||
@ -103,3 +107,103 @@ func BytesHex(name string, value []byte, usage string) *[]byte {
|
|||||||
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded
|
||||||
|
type bytesBase64Value []byte
|
||||||
|
|
||||||
|
// String implements pflag.Value.String.
|
||||||
|
func (bytesBase64 bytesBase64Value) String() string {
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(bytesBase64))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set implements pflag.Value.Set.
|
||||||
|
func (bytesBase64 *bytesBase64Value) Set(value string) error {
|
||||||
|
bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytesBase64 = bin
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type implements pflag.Value.Type.
|
||||||
|
func (*bytesBase64Value) Type() string {
|
||||||
|
return "bytesBase64"
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value {
|
||||||
|
*p = val
|
||||||
|
return (*bytesBase64Value)(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesBase64ValueConv(sval string) (interface{}, error) {
|
||||||
|
|
||||||
|
bin, err := base64.StdEncoding.DecodeString(sval)
|
||||||
|
if err == nil {
|
||||||
|
return bin, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBytesBase64 return the []byte value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) {
|
||||||
|
val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.([]byte), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesBase64VarP(p, name, "", value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesBase64VarP(p, name, shorthand, value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesBase64P(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesBase64P(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
|
|||||||
10
vendor/github.com/spf13/pflag/flag.go
generated
vendored
10
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -925,13 +925,16 @@ func stripUnknownFlagValue(args []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
first := args[0]
|
first := args[0]
|
||||||
if first[0] == '-' {
|
if len(first) > 0 && first[0] == '-' {
|
||||||
//--unknown --next-flag ...
|
//--unknown --next-flag ...
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
//--unknown arg ... (args will be arg ...)
|
//--unknown arg ... (args will be arg ...)
|
||||||
return args[1:]
|
if len(args) > 1 {
|
||||||
|
return args[1:]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
@ -990,11 +993,12 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||||
|
outArgs = args
|
||||||
|
|
||||||
if strings.HasPrefix(shorthands, "test.") {
|
if strings.HasPrefix(shorthands, "test.") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outArgs = args
|
|
||||||
outShorts = shorthands[1:]
|
outShorts = shorthands[1:]
|
||||||
c := shorthands[0]
|
c := shorthands[0]
|
||||||
|
|
||||||
|
|||||||
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- stringToInt Value
|
||||||
|
type stringToIntValue struct {
|
||||||
|
value *map[string]int
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue {
|
||||||
|
ssv := new(stringToIntValue)
|
||||||
|
ssv.value = p
|
||||||
|
*ssv.value = val
|
||||||
|
return ssv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: a=1,b=2
|
||||||
|
func (s *stringToIntValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
for k, v := range out {
|
||||||
|
(*s.value)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToIntValue) Type() string {
|
||||||
|
return "stringToInt"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToIntValue) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
i := 0
|
||||||
|
for k, v := range *s.value {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteRune(',')
|
||||||
|
}
|
||||||
|
buf.WriteString(k)
|
||||||
|
buf.WriteRune('=')
|
||||||
|
buf.WriteString(strconv.Itoa(v))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return "[" + buf.String() + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToIntConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// An empty string would cause an empty map
|
||||||
|
if len(val) == 0 {
|
||||||
|
return map[string]int{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringToInt return the map[string]int value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) {
|
||||||
|
val, err := f.getFlagType(name, "stringToInt", stringToIntConv)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]int{}, err
|
||||||
|
}
|
||||||
|
return val.(map[string]int), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]int variable in which to store the values of the multiple flags.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||||
|
f.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||||
|
f.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]int variable in which to store the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||||
|
CommandLine.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||||
|
CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||||
|
p := map[string]int{}
|
||||||
|
f.StringToIntVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||||
|
p := map[string]int{}
|
||||||
|
f.StringToIntVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||||
|
return CommandLine.StringToIntP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||||
|
return CommandLine.StringToIntP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- stringToString Value
|
||||||
|
type stringToStringValue struct {
|
||||||
|
value *map[string]string
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
|
||||||
|
ssv := new(stringToStringValue)
|
||||||
|
ssv.value = p
|
||||||
|
*ssv.value = val
|
||||||
|
return ssv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: a=1,b=2
|
||||||
|
func (s *stringToStringValue) Set(val string) error {
|
||||||
|
var ss []string
|
||||||
|
n := strings.Count(val, "=")
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", val)
|
||||||
|
case 1:
|
||||||
|
ss = append(ss, strings.Trim(val, `"`))
|
||||||
|
default:
|
||||||
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
|
var err error
|
||||||
|
ss, err = r.Read()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[string]string, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
out[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
for k, v := range out {
|
||||||
|
(*s.value)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToStringValue) Type() string {
|
||||||
|
return "stringToString"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToStringValue) String() string {
|
||||||
|
records := make([]string, 0, len(*s.value)>>1)
|
||||||
|
for k, v := range *s.value {
|
||||||
|
records = append(records, k+"="+v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := csv.NewWriter(&buf)
|
||||||
|
if err := w.Write(records); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
w.Flush()
|
||||||
|
return "[" + strings.TrimSpace(buf.String()) + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToStringConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// An empty string would cause an empty map
|
||||||
|
if len(val) == 0 {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
}
|
||||||
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
|
ss, err := r.Read()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out := make(map[string]string, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
out[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringToString return the map[string]string value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
|
||||||
|
val, err := f.getFlagType(name, "stringToString", stringToStringConv)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]string{}, err
|
||||||
|
}
|
||||||
|
return val.(map[string]string), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||||
|
f.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||||
|
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a map[string]string variable in which to store the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||||
|
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||||
|
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||||
|
p := map[string]string{}
|
||||||
|
f.StringToStringVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||||
|
p := map[string]string{}
|
||||||
|
f.StringToStringVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||||
|
return CommandLine.StringToStringP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||||
|
return CommandLine.StringToStringP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user