gobgpのgrpcとかbgpのflowspecとか見てきた流れで、ならばgobgpdつかっているときにcliスクリプトからflowspec投げるには?ということで、とりあえずできるようになる要点をピックアップ。デーモンconfigurationではafi-safi-name = "ipv4-flowspec", afi-safi-name = "ipv6-flowspec"を設定。
必須import
from google.protobuf.any_pb2 import Any import gobgp_pb2 import gobgp_pb2_grpc import attribute_pb2
デーモンとの通信チャネル作成
def connfactory(host, port):
channel = grpc.insecure_channel(host + ':' + str(50051))
stub = gobgp_pb2_grpc.GobgpApiStub(channel)
return stub最後の実行で、デーモンサイトのlocal-asnが必要
def getbgp(stub):
g = stub.GetBgp(gobgp_pb2.GetBgpRequest())
ret = {}
for c in g.ListFields()[0]:
if c.__class__.__name__ != "Global":
continue
for f in c.ListFields():
if f[0].__class__.__name__ == "FieldDescriptor":
ret[f[0].name] = f[1]
return retIPv4 or Ipv6 on flowspec おまじない変数
def family(v):
afi = (v==4 and gobgp_pb2.Family.AFI_IP or gobgp_pb2.Family.Family.AFI_IP6)
return gobgp_pb2.Family(afi=afi, safi=gobgp_pb2.Family.SAFI_FLOW_SPEC_UNICAST)Network Layer Reachability Information部分の作成
def build_flowspecipprefix(rules, typeval, ipprefix):
assert(typeval in (1, 2))
s = ipprefix.split('/')
prefix = s[0]
prefix_len = (len(s)==2 and int(s[1])) or (prefix.find(':')>-1 and 128 or 32) # be more seriously
o = Any()
o.Pack(attribute_pb2.FlowSpecIPPrefix(type=typeval,prefix_len = prefix_len, prefix = prefix))
rules.append(o)
def build_flowspeccomponent(rules, typeval, conditions):
assert(typeval in (3, 4, 5, 6,))
items = []
for op, value in conditions:
items.append(attribute_pb2.FlowSpecComponentItem(op=op, value=value))
o = Any()
o.Pack(attribute_pb2.FlowSpecComponent(type=typeval, items=items))
rules.append(o)flowspec action
def build_action(rate):
rate = float(rate)
o = Any()
o.Pack(attribute_pb2.TrafficRateExtended(rate=rate)) # can't let into 'as'
return attribute_pb2.ExtendedCommunitiesAttribute(communities=[o])AddPathで必要な引数コンテナの作成ヘルパ
def build_pattrs(v, nlri, rate, origin):
ac = Any()
ac.Pack(build_action(rate))
nullip = (v==4 and "0.0.0.0" or "::0")
nh = Any()
nh.Pack(attribute_pb2.MpReachNLRIAttribute(family=family(v), nlris=[nlri], next_hops=[nullip]))
og = Any()
og.Pack(attribute_pb2.OriginAttribute(origin=origin))
return (ac, nh, og)
def build_nlri(rules):
o = Any()
o.Pack(attribute_pb2.FlowSpecNLRI(rules=rules))
return o材料がそろったところで実行例。
src: 1.2.3.4/32
dst:9.8.7.6/32
protocol: udp
port(両方向): 1900,11211
rate-limit 0.0 bytes/sec :=> discard
の条件について
ver = 4
rules = []
build_flowspecipprefix(rules, 1, "1.2.3.4/32")
build_flowspecipprefix(rules, 2, "9.8.7.6/32")
build_flowspeccomponent(rules, 3, [(1,17)])
build_flowspeccomponent(rules, 4, [(1,1900),(1,11211),])
nlri = build_nlri(rules)
stub = connfactory('127.0.0.1', 50051)
source_asn = getbgp(stub)['as']
path = gobgp_pb2.Path(family=family(ver), nlri=nlri, pattrs=build_pattrs(ver, nlri, 0.0, 0), source_asn=source_asn)
stub.AddPath(gobgp_pb2.AddPathRequest(table_type=gobgp_pb2.GLOBAL,path=path),timeout=10)情報が入ったかどうかをgobgpコマンドで確認
nao@hnd:~/gobgp$ ./gobgp global rib -a ipv4-flowspec
Network Next Hop AS_PATH Age Attrs
*> [destination: 1.2.3.4/32][source: 9.8.7.6/32][protocol: ==udp][port: ==1900 ==11211] fictitious 00:00:27 [{Extcomms: [discard]} {Origin: i}]以上です。
参考: