From 6ce1576ee91dcd6f325b4c82612f32554d5181c1 Mon Sep 17 00:00:00 2001 From: hedi bouattour Date: Mon, 12 Sep 2022 12:27:13 +0000 Subject: [PATCH 1/3] agent: remove node watcher and use route update msgs from felix --- calico-vpp-agent/cni/cni_node_test.go | 14 +- calico-vpp-agent/common/common.go | 34 +- calico-vpp-agent/common/pubsub.go | 3 + calico-vpp-agent/connectivity/connectivity.go | 3 +- .../connectivity/connectivity_server.go | 23 +- calico-vpp-agent/connectivity/ipsec.go | 2 +- calico-vpp-agent/connectivity/wireguard.go | 10 +- calico-vpp-agent/policy/messages.go | 4 + calico-vpp-agent/policy/policy_server.go | 37 +- calico-vpp-agent/proto/felixbackend.pb.go | 522 +++++++++--------- calico-vpp-agent/proto/felixbackend.proto | 3 + calico-vpp-agent/routing/routing_server.go | 6 +- calico-vpp-agent/services/service_server.go | 5 +- calico-vpp-agent/watchers/kernel_watcher.go | 138 +++++ calico-vpp-agent/watchers/nodes_watcher.go | 160 +++--- calico-vpp-agent/watchers/peers_watcher.go | 35 +- calico-vpp-agent/watchers/prefix_watcher.go | 5 +- .../watchers/srv6_localsid_watcher.go | 5 +- 18 files changed, 616 insertions(+), 393 deletions(-) create mode 100644 calico-vpp-agent/watchers/kernel_watcher.go diff --git a/calico-vpp-agent/cni/cni_node_test.go b/calico-vpp-agent/cni/cni_node_test.go index 6d79ba5df..279426744 100644 --- a/calico-vpp-agent/cni/cni_node_test.go +++ b/calico-vpp-agent/cni/cni_node_test.go @@ -146,7 +146,7 @@ var _ = Describe("Node-related functionality of CNI", func() { } connectivityServer = connectivity.NewConnectivityServer(vpp, ipamStub, client, log.WithFields(logrus.Fields{"subcomponent": "connectivity"})) - connectivityServer.SetOurBGPSpec(&oldv3.NodeBGPSpec{}) + connectivityServer.SetOurBGPSpec(&common.LocalNodeSpec{}) if felixConfig == nil { felixConfig = &config.Config{} } @@ -563,13 +563,9 @@ var _ = Describe("Node-related functionality of CNI", func() { Expect(err).ToNot(HaveOccurred(), "could not call ForceProviderEnableDisable") addedNodePublicKey := "public-key-for-added-node" // max 32 characters due to VPP binapi - connectivityServer.ForceNodeAddition(oldv3.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: AddedNodeName, - }, - Status: oldv3.NodeStatus{ - WireguardPublicKey: base64.StdEncoding.EncodeToString([]byte(addedNodePublicKey)), - }, + connectivityServer.ForceNodeAddition(common.LocalNodeSpec{ + Name: AddedNodeName, + WireguardPublicKey: base64.StdEncoding.EncodeToString([]byte(addedNodePublicKey)), }, net.ParseIP(AddedNodeIP)) err = connectivityServer.UpdateIPConnectivity(&common.NodeConnectivity{ Dst: *ipNet(AddedNodeIP + "/24"), @@ -1017,7 +1013,7 @@ func assertNextNodeLink(node, linkedNextNode string, vpp *vpplink.VppLink) int { } func configureBGPNodeIPAddresses(connectivityServer *connectivity.ConnectivityServer) { - connectivityServer.SetOurBGPSpec(&oldv3.NodeBGPSpec{ + connectivityServer.SetOurBGPSpec(&common.LocalNodeSpec{ IPv4Address: ThisNodeIP + "/24", IPv6Address: ThisNodeIPv6 + "/128", }) diff --git a/calico-vpp-agent/common/common.go b/calico-vpp-agent/common/common.go index 10fdc9cb3..9aa1a10bf 100644 --- a/calico-vpp-agent/common/common.go +++ b/calico-vpp-agent/common/common.go @@ -34,7 +34,7 @@ import ( "github.com/golang/protobuf/ptypes/any" bgpapi "github.com/osrg/gobgp/api" calicov3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" + "github.com/projectcalico/api/pkg/lib/numorstring" "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/proto" "github.com/projectcalico/vpp-dataplane/vpplink" "github.com/projectcalico/vpp-dataplane/vpplink/types" @@ -55,6 +55,19 @@ type PolicyServerIpam interface { IPNetNeedsSNAT(prefix *net.IPNet) bool GetPrefixIPPool(prefix *net.IPNet) *proto.IPAMPool } +type NodeRouteRemove struct { + Dst string + Name string +} + +type LocalNodeSpec struct { + ASNumber *numorstring.ASNumber + Labels map[string]string + Name string + IPv4Address string + IPv6Address string + WireguardPublicKey string +} // CreateVppLink creates new link to VPP and waits for VPP to be up and running (by using simple VPP API call) func CreateVppLink(socket string, log *logrus.Entry) (vpp *vpplink.VppLink, err error) { @@ -173,11 +186,6 @@ var ( BgpFamilySRv6IPv6 = bgpapi.Family{Afi: bgpapi.Family_AFI_IP6, Safi: bgpapi.Family_SAFI_SR_POLICY} ) -type NodeState struct { - oldv3.Node - SweepFlag bool -} - func v46ify(s string, isv6 bool) string { if isv6 { return s + "-v6" @@ -458,7 +466,7 @@ type SRv6Tunnel struct { Priority uint32 } -func GetBGPSpecAddresses(nodeBGPSpec *oldv3.NodeBGPSpec) (*net.IP, *net.IP) { +func GetBGPSpecAddresses(nodeBGPSpec *LocalNodeSpec) (*net.IP, *net.IP) { var ip4 *net.IP var ip6 *net.IP if nodeBGPSpec.IPv4Address != "" { @@ -476,7 +484,7 @@ func GetBGPSpecAddresses(nodeBGPSpec *oldv3.NodeBGPSpec) (*net.IP, *net.IP) { return ip4, ip6 } -func GetBGPSpecIPNet(nodeBGPSpec *oldv3.NodeBGPSpec) (ip4 *net.IPNet, ip6 *net.IPNet) { +func GetBGPSpecIPNet(nodeBGPSpec *LocalNodeSpec) (ip4 *net.IPNet, ip6 *net.IPNet) { if nodeBGPSpec.IPv4Address != "" { _, ipNet, err := net.ParseCIDR(nodeBGPSpec.IPv4Address) if err == nil { @@ -492,17 +500,17 @@ func GetBGPSpecIPNet(nodeBGPSpec *oldv3.NodeBGPSpec) (ip4 *net.IPNet, ip6 *net.I return ip4, ip6 } -func GetNodeSpecAddresses(node *oldv3.Node) (string, string) { +func GetNodeSpecAddresses(node *LocalNodeSpec) (string, string) { nodeIP4 := "" nodeIP6 := "" - if node.Spec.BGP.IPv4Address != "" { - addr, _, err := net.ParseCIDR(node.Spec.BGP.IPv4Address) + if node.IPv4Address != "" { + addr, _, err := net.ParseCIDR(node.IPv4Address) if err == nil { nodeIP4 = addr.String() } } - if node.Spec.BGP.IPv6Address != "" { - addr, _, err := net.ParseCIDR(node.Spec.BGP.IPv6Address) + if node.IPv6Address != "" { + addr, _, err := net.ParseCIDR(node.IPv6Address) if err == nil { nodeIP6 = addr.String() } diff --git a/calico-vpp-agent/common/pubsub.go b/calico-vpp-agent/common/pubsub.go index 8768949a0..ebe22d39b 100644 --- a/calico-vpp-agent/common/pubsub.go +++ b/calico-vpp-agent/common/pubsub.go @@ -64,6 +64,9 @@ const ( IpamPoolUpdate CalicoVppEventType = "IpamPoolUpdate" IpamPoolRemove CalicoVppEventType = "IpamPoolRemove" + + NodeRouteUpdate CalicoVppEventType = "NodeRouteUpdate" + NodeRouteDelete CalicoVppEventType = "NodeRouteDelete" ) var ( diff --git a/calico-vpp-agent/connectivity/connectivity.go b/calico-vpp-agent/connectivity/connectivity.go index cbbc5b59b..7aff22c90 100644 --- a/calico-vpp-agent/connectivity/connectivity.go +++ b/calico-vpp-agent/connectivity/connectivity.go @@ -20,7 +20,6 @@ import ( "net" felixConfig "github.com/projectcalico/calico/felix/config" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" "github.com/projectcalico/vpp-dataplane/vpplink" @@ -55,7 +54,7 @@ type ConnectivityProvider interface { EnableDisable(isEnable bool) } -func (p *ConnectivityProviderData) GetNodeByIp(addr net.IP) *oldv3.Node { +func (p *ConnectivityProviderData) GetNodeByIp(addr net.IP) *common.LocalNodeSpec { return p.server.GetNodeByIp(addr) } func (p *ConnectivityProviderData) GetNodeIPs() (*net.IP, *net.IP) { diff --git a/calico-vpp-agent/connectivity/connectivity_server.go b/calico-vpp-agent/connectivity/connectivity_server.go index 409e23285..d2c4b9008 100644 --- a/calico-vpp-agent/connectivity/connectivity_server.go +++ b/calico-vpp-agent/connectivity/connectivity_server.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" felixConfig "github.com/projectcalico/calico/felix/config" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/projectcalico/calico/libcalico-go/lib/backend/encap" calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/sirupsen/logrus" @@ -40,11 +39,11 @@ type ConnectivityServer struct { connectivityMap map[string]common.NodeConnectivity policyServerIpam common.PolicyServerIpam Clientv3 calicov3cli.Interface - nodeBGPSpec *oldv3.NodeBGPSpec - vpp *vpplink.VppLink + nodeBGPSpec *common.LocalNodeSpec + vpp *vpplink.VppLink felixConfig *felixConfig.Config - nodeByAddr map[string]oldv3.Node + nodeByAddr map[string]common.LocalNodeSpec connectivityEventChan chan common.CalicoVppEvent @@ -58,7 +57,7 @@ const ( DeleteChange change = 1 ) -func (s *ConnectivityServer) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (s *ConnectivityServer) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { s.nodeBGPSpec = nodeBGPSpec } @@ -75,7 +74,7 @@ func NewConnectivityServer(vpp *vpplink.VppLink, policyServerIpam common.PolicyS Clientv3: clientv3, connectivityMap: make(map[string]common.NodeConnectivity), connectivityEventChan: make(chan common.CalicoVppEvent, common.ChanSize), - nodeByAddr: make(map[string]oldv3.Node), + nodeByAddr: make(map[string]common.LocalNodeSpec), networks: make(map[uint32]watchers.NetworkDefinition), } @@ -110,7 +109,7 @@ func isCrossSubnet(gw net.IP, subnet net.IPNet) bool { return !subnet.Contains(gw) } -func (s *ConnectivityServer) GetNodeByIp(addr net.IP) *oldv3.Node { +func (s *ConnectivityServer) GetNodeByIp(addr net.IP) *common.LocalNodeSpec { ns, found := s.nodeByAddr[addr.String()] if !found { return nil @@ -175,8 +174,8 @@ func (s *ConnectivityServer) ServeConnectivity(t *tomb.Tomb) error { s.log.Errorf("Error while deleting connectivity %s", err) } case common.PeerNodeStateChanged: - old, _ := evt.Old.(*oldv3.Node) - new, _ := evt.New.(*oldv3.Node) + old, _ := evt.Old.(*common.LocalNodeSpec) + new, _ := evt.New.(*common.LocalNodeSpec) if old != nil { oldV4IP, oldV6IP := common.GetNodeSpecAddresses(old) if oldV4IP != "" { @@ -196,9 +195,9 @@ func (s *ConnectivityServer) ServeConnectivity(t *tomb.Tomb) error { } } if old != nil && new != nil { - change := common.GetStringChangeType(old.Status.WireguardPublicKey, new.Status.WireguardPublicKey) + change := common.GetStringChangeType(old.WireguardPublicKey, new.WireguardPublicKey) if change != common.ChangeSame { - s.log.Infof("connectivity(upd) WireguardPublicKey Changed (%s) %s->%s", old.Name, old.Status.WireguardPublicKey, new.Status.WireguardPublicKey) + s.log.Infof("connectivity(upd) WireguardPublicKey Changed (%s) %s->%s", old.Name, old.WireguardPublicKey, new.WireguardPublicKey) s.updateAllIPConnectivity() } } @@ -375,6 +374,6 @@ func (s *ConnectivityServer) ForceProviderEnableDisable(providerType string, ena // ForceNodeAddition will add other node information as provided by calico configuration // The usage is mainly for testing purposes. -func (s *ConnectivityServer) ForceNodeAddition(newNode oldv3.Node, newNodeIP net.IP) { +func (s *ConnectivityServer) ForceNodeAddition(newNode common.LocalNodeSpec, newNodeIP net.IP) { s.nodeByAddr[newNodeIP.String()] = newNode } diff --git a/calico-vpp-agent/connectivity/ipsec.go b/calico-vpp-agent/connectivity/ipsec.go index 973630884..d45a18f57 100644 --- a/calico-vpp-agent/connectivity/ipsec.go +++ b/calico-vpp-agent/connectivity/ipsec.go @@ -332,7 +332,7 @@ func (p *IpsecProvider) forceOtherNodeIp4(addr net.IP) (ip4 net.IP, err error) { if otherNode == nil { return nil, fmt.Errorf("Didnt find an ip4 for ip %s", addr.String()) } - nodeIP, _, err := net.ParseCIDR(otherNode.Spec.BGP.IPv4Address) + nodeIP, _, err := net.ParseCIDR(otherNode.IPv4Address) if err != nil { return nil, errors.Wrapf(err, "Didnt find an ip4 for ip %s", addr.String()) } diff --git a/calico-vpp-agent/connectivity/wireguard.go b/calico-vpp-agent/connectivity/wireguard.go index 50449d547..e329e7e9a 100644 --- a/calico-vpp-agent/connectivity/wireguard.go +++ b/calico-vpp-agent/connectivity/wireguard.go @@ -49,7 +49,7 @@ func (p *WireguardProvider) Enabled(cn *common.NodeConnectivity) bool { return false } node := p.GetNodeByIp(cn.NextHop) - return node.Status.WireguardPublicKey != "" + return node.WireguardPublicKey != "" } func (p *WireguardProvider) getWireguardPort() uint16 { @@ -62,14 +62,14 @@ func (p *WireguardProvider) getWireguardPort() uint16 { func (p *WireguardProvider) getNodePublicKey(cn *common.NodeConnectivity) ([]byte, error) { node := p.GetNodeByIp(cn.NextHop) - if node.Status.WireguardPublicKey == "" { + if node.WireguardPublicKey == "" { return nil, fmt.Errorf("no public key for node=%s", node.Name) } - p.log.Infof("connectivity(add) Wireguard nodeName=%s pubKey=%s", node.Name, node.Status.WireguardPublicKey) - key, err := base64.StdEncoding.DecodeString(node.Status.WireguardPublicKey) + p.log.Infof("connectivity(add) Wireguard nodeName=%s pubKey=%s", node.Name, node.WireguardPublicKey) + key, err := base64.StdEncoding.DecodeString(node.WireguardPublicKey) if err != nil { - return nil, errors.Wrapf(err, "Error decoding wireguard public key %s", node.Status.WireguardPublicKey) + return nil, errors.Wrapf(err, "Error decoding wireguard public key %s", node.WireguardPublicKey) } return key, nil } diff --git a/calico-vpp-agent/policy/messages.go b/calico-vpp-agent/policy/messages.go index 34cb38a55..49df6ee49 100644 --- a/calico-vpp-agent/policy/messages.go +++ b/calico-vpp-agent/policy/messages.go @@ -99,6 +99,10 @@ func (s *Server) RecvMessage(conn net.Conn) (msg interface{}, err error) { msg = payload.HostMetadataUpdate case *proto.ToDataplane_HostMetadataRemove: msg = payload.HostMetadataRemove + case *proto.ToDataplane_RouteUpdate: + msg = payload.RouteUpdate + case *proto.ToDataplane_RouteRemove: + msg = payload.RouteRemove case *proto.ToDataplane_IpamPoolUpdate: msg = payload.IpamPoolUpdate case *proto.ToDataplane_IpamPoolRemove: diff --git a/calico-vpp-agent/policy/policy_server.go b/calico-vpp-agent/policy/policy_server.go index 864892aa5..cc677e335 100644 --- a/calico-vpp-agent/policy/policy_server.go +++ b/calico-vpp-agent/policy/policy_server.go @@ -28,7 +28,6 @@ import ( "github.com/pkg/errors" felixConfig "github.com/projectcalico/calico/felix/config" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" tomb "gopkg.in/tomb.v2" @@ -96,9 +95,10 @@ type Server struct { ippoolmap map[string]proto.IPAMPoolUpdate ippoolLock sync.RWMutex + hosts map[string]string } -func (s *Server) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (s *Server) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { ip4, ip6 := common.GetBGPSpecAddresses(nodeBGPSpec) s.ip4 = ip4 s.ip6 = ip6 @@ -130,6 +130,7 @@ func NewPolicyServer(vpp *vpplink.VppLink, log *logrus.Entry) (*Server, error) { felixConfig: felixConfig.New(), ippoolmap: make(map[string]proto.IPAMPoolUpdate), + hosts: make(map[string]string), } reg := common.RegisterHandler(server.policyServerEventChan, "policy server events") @@ -554,6 +555,10 @@ func (s *Server) handleFelixUpdate(msg interface{}) (err error) { err = s.handleNamespaceRemove(m, pending) case *proto.GlobalBGPConfigUpdate: err = s.handleGlobalBGPConfigUpdate(m, pending) + case *proto.RouteUpdate: + err = s.handleRouteUpdate(m, pending) + case *proto.RouteRemove: + err = s.handleRouteRemove(m, pending) default: s.log.Warnf("Unhandled message from felix: %v", m) } @@ -1095,6 +1100,34 @@ func (s *Server) handleHostMetadataRemove(msg *proto.HostMetadataRemove, pending return nil } +func (s *Server) handleRouteUpdate(msg *proto.RouteUpdate, pending bool) (err error) { + // node update (local or remote host) + if msg.Type == proto.RouteType_REMOTE_HOST || msg.Type == proto.RouteType_LOCAL_HOST { + s.log.Infof("received node update msg from felix: %+v", msg) + s.hosts[msg.Dst] = msg.DstNodeName + common.SendEvent(common.CalicoVppEvent{ + Type: common.NodeRouteUpdate, + New: msg, + }) + } + return nil +} + +func (s *Server) handleRouteRemove(msg *proto.RouteRemove, pending bool) (err error) { + // cannot directly tell which type of route that is, so look in map? + if name, ok := s.hosts[msg.Dst]; ok { + s.log.Infof("received node remove msg from felix: %+v: %s", msg, name) + common.SendEvent(common.CalicoVppEvent{ + Type: common.NodeRouteDelete, + Old: &common.NodeRouteRemove{ + Dst: msg.Dst, + Name: name, + }, + }) + } + return nil +} + func (s *Server) handleIpamPoolUpdate(msg *proto.IPAMPoolUpdate, pending bool) (err error) { if msg != nil { s.ippoolLock.Lock() diff --git a/calico-vpp-agent/proto/felixbackend.pb.go b/calico-vpp-agent/proto/felixbackend.pb.go index 84ea5768a..41f512579 100644 --- a/calico-vpp-agent/proto/felixbackend.pb.go +++ b/calico-vpp-agent/proto/felixbackend.pb.go @@ -3779,14 +3779,17 @@ type RouteUpdate struct { // The name of the node holding this destination, if this route targets a calico node. DstNodeName string `protobuf:"bytes,4,opt,name=dst_node_name,json=dstNodeName,proto3" json:"dst_node_name,omitempty"` // IP of the node holding this destination. - DstNodeIp string `protobuf:"bytes,5,opt,name=dst_node_ip,json=dstNodeIp,proto3" json:"dst_node_ip,omitempty"` - SameSubnet bool `protobuf:"varint,7,opt,name=same_subnet,json=sameSubnet,proto3" json:"same_subnet,omitempty"` - NatOutgoing bool `protobuf:"varint,8,opt,name=nat_outgoing,json=natOutgoing,proto3" json:"nat_outgoing,omitempty"` - LocalWorkload bool `protobuf:"varint,9,opt,name=local_workload,json=localWorkload,proto3" json:"local_workload,omitempty"` - TunnelType *TunnelType `protobuf:"bytes,10,opt,name=tunnel_type,json=tunnelType,proto3" json:"tunnel_type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + DstNodeIp string `protobuf:"bytes,5,opt,name=dst_node_ip,json=dstNodeIp,proto3" json:"dst_node_ip,omitempty"` + SameSubnet bool `protobuf:"varint,7,opt,name=same_subnet,json=sameSubnet,proto3" json:"same_subnet,omitempty"` + NatOutgoing bool `protobuf:"varint,8,opt,name=nat_outgoing,json=natOutgoing,proto3" json:"nat_outgoing,omitempty"` + LocalWorkload bool `protobuf:"varint,9,opt,name=local_workload,json=localWorkload,proto3" json:"local_workload,omitempty"` + TunnelType *TunnelType `protobuf:"bytes,10,opt,name=tunnel_type,json=tunnelType,proto3" json:"tunnel_type,omitempty"` + Labels map[string]string `protobuf:"bytes,11,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Asnumber string `protobuf:"bytes,12,opt,name=asnumber,proto3" json:"asnumber,omitempty"` + WireguardPublicKey string `protobuf:"bytes,13,opt,name=wireguard_public_key,json=wireguardPublicKey,proto3" json:"wireguard_public_key,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *RouteUpdate) Reset() { *m = RouteUpdate{} } @@ -3876,6 +3879,27 @@ func (m *RouteUpdate) GetTunnelType() *TunnelType { return nil } +func (m *RouteUpdate) GetLabels() map[string]string { + if m != nil { + return m.Labels + } + return nil +} + +func (m *RouteUpdate) GetAsnumber() string { + if m != nil { + return m.Asnumber + } + return "" +} + +func (m *RouteUpdate) GetWireguardPublicKey() string { + if m != nil { + return m.WireguardPublicKey + } + return "" +} + type RouteRemove struct { Dst string `protobuf:"bytes,2,opt,name=dst,proto3" json:"dst,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -4475,6 +4499,7 @@ func init() { proto.RegisterType((*NamespaceID)(nil), "felix.NamespaceID") proto.RegisterType((*TunnelType)(nil), "felix.TunnelType") proto.RegisterType((*RouteUpdate)(nil), "felix.RouteUpdate") + proto.RegisterMapType((map[string]string)(nil), "felix.RouteUpdate.LabelsEntry") proto.RegisterType((*RouteRemove)(nil), "felix.RouteRemove") proto.RegisterType((*VXLANTunnelEndpointUpdate)(nil), "felix.VXLANTunnelEndpointUpdate") proto.RegisterType((*VXLANTunnelEndpointRemove)(nil), "felix.VXLANTunnelEndpointRemove") @@ -4490,253 +4515,256 @@ func init() { func init() { proto.RegisterFile("felixbackend.proto", fileDescriptor_a792994fb90b9e3e) } var fileDescriptor_a792994fb90b9e3e = []byte{ - // 3926 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x4b, 0x73, 0x1c, 0xc9, - 0x56, 0x56, 0xb7, 0xa4, 0x56, 0xf7, 0xe9, 0x87, 0xda, 0xa9, 0x57, 0x4b, 0xb6, 0x6c, 0x4f, 0x79, - 0x26, 0x46, 0x33, 0xdc, 0xf1, 0x18, 0x8d, 0xdd, 0xbe, 0x1e, 0x2e, 0x73, 0x43, 0x96, 0x34, 0xa3, - 0x9e, 0xb1, 0x25, 0x45, 0x49, 0xe3, 0xe1, 0x12, 0x37, 0xa2, 0x28, 0x55, 0xa5, 0xa4, 0xc2, 0xd5, - 0x55, 0x35, 0x55, 0xd9, 0x7a, 0x5c, 0x56, 0x5c, 0x2e, 0x0b, 0x82, 0x20, 0x58, 0x10, 0x41, 0xf0, - 0x03, 0x58, 0x11, 0xfc, 0x03, 0x16, 0xb0, 0x21, 0x82, 0xfb, 0x23, 0xf8, 0x03, 0xec, 0x58, 0xb0, - 0x27, 0x32, 0xf3, 0x64, 0xd6, 0xa3, 0xab, 0x65, 0x99, 0x00, 0x56, 0xea, 0x3c, 0x79, 0xce, 0x97, - 0x5f, 0x9e, 0x7c, 0x9d, 0x93, 0x95, 0x02, 0x72, 0x4a, 0x7d, 0xef, 0xea, 0xc4, 0x76, 0xde, 0xd2, - 0xc0, 0x7d, 0x1c, 0xc5, 0x21, 0x0b, 0xc9, 0xac, 0x90, 0x19, 0x6d, 0x68, 0x1e, 0x5d, 0x07, 0x8e, - 0x49, 0x7f, 0x1c, 0xd1, 0x84, 0x19, 0x7f, 0xb3, 0x04, 0xcd, 0xe3, 0x70, 0xc7, 0x66, 0x76, 0xe4, - 0xdb, 0x01, 0x25, 0x1f, 0xc3, 0x7c, 0xc2, 0xab, 0x02, 0x87, 0x5a, 0xc1, 0x68, 0x78, 0x42, 0xe3, - 0xde, 0xfc, 0xc3, 0xca, 0xc6, 0x8c, 0xd9, 0x51, 0xe2, 0x7d, 0x21, 0x25, 0x1b, 0x30, 0xe7, 0x05, - 0x56, 0x72, 0x1d, 0x38, 0xbd, 0xca, 0xc3, 0xca, 0x46, 0x73, 0xb3, 0xfd, 0x58, 0x34, 0xf0, 0x78, - 0x10, 0x70, 0xfc, 0xbd, 0x29, 0xb3, 0xe6, 0x89, 0x5f, 0xe4, 0x39, 0xb4, 0xbc, 0x28, 0xa1, 0xcc, - 0x1a, 0x45, 0xae, 0xcd, 0x68, 0xaf, 0x2a, 0xd4, 0x89, 0x52, 0x3f, 0x3c, 0xa2, 0xec, 0x7b, 0x51, - 0xb3, 0x37, 0x65, 0x36, 0x85, 0xa6, 0x2c, 0x92, 0x6f, 0x80, 0x48, 0x43, 0x97, 0xfa, 0xcc, 0x56, - 0xe6, 0xd3, 0xc2, 0x7c, 0x25, 0x6b, 0xbe, 0xc3, 0xeb, 0x35, 0x46, 0x57, 0x18, 0x65, 0x64, 0x29, - 0x83, 0x98, 0x0e, 0xc3, 0x0b, 0xda, 0x9b, 0x19, 0x67, 0x60, 0x8a, 0x1a, 0xcd, 0x40, 0x16, 0xc9, - 0x21, 0x2c, 0xd9, 0x0e, 0xf3, 0x2e, 0xa8, 0x15, 0xc5, 0xe1, 0xa9, 0xe7, 0x53, 0x45, 0x62, 0x56, - 0x20, 0xac, 0x21, 0xc2, 0x96, 0xd0, 0x39, 0x94, 0x2a, 0x9a, 0xc7, 0x82, 0x3d, 0x2e, 0x2e, 0x41, - 0x44, 0x4e, 0xb5, 0xc9, 0x88, 0x9a, 0x5b, 0x1e, 0x11, 0x39, 0xbe, 0x86, 0x45, 0x85, 0x18, 0xfa, - 0x9e, 0x73, 0xad, 0x28, 0xce, 0x09, 0xc0, 0xd5, 0x3c, 0xa0, 0xd0, 0xd0, 0x0c, 0x89, 0x3d, 0x26, - 0x1d, 0x87, 0x43, 0x7e, 0xf5, 0x89, 0x70, 0x9a, 0x5e, 0x0e, 0x2e, 0x65, 0x77, 0x1e, 0x26, 0xcc, - 0xa2, 0x81, 0x1b, 0x85, 0x5e, 0xa0, 0x27, 0x41, 0x23, 0x07, 0xb7, 0x17, 0x26, 0x6c, 0x17, 0x35, - 0x52, 0x76, 0xe7, 0x63, 0xd2, 0x71, 0x38, 0x64, 0x07, 0x13, 0xe1, 0x52, 0x76, 0xe7, 0x63, 0x52, - 0xf2, 0x0b, 0xe8, 0x5d, 0x86, 0xf1, 0x5b, 0x3f, 0xb4, 0xdd, 0x31, 0x86, 0x4d, 0x01, 0xb9, 0x8e, - 0x90, 0x3f, 0xa0, 0xda, 0x18, 0xcb, 0xe5, 0xcb, 0xd2, 0x9a, 0x72, 0x68, 0x64, 0xdb, 0xba, 0x11, - 0x5a, 0x33, 0x1e, 0x83, 0x46, 0xd6, 0x5f, 0x42, 0xdb, 0x09, 0x83, 0x53, 0xef, 0x4c, 0x51, 0x6d, - 0x0b, 0xbc, 0x05, 0xc4, 0xdb, 0x16, 0x75, 0x9a, 0x60, 0xcb, 0xc9, 0x94, 0xb5, 0x03, 0x87, 0x94, - 0xd9, 0xae, 0x9d, 0xae, 0xaa, 0xce, 0x98, 0x03, 0x5f, 0xa3, 0x46, 0x7e, 0x3c, 0xf2, 0xd2, 0x71, - 0x38, 0xec, 0x21, 0x99, 0x08, 0x97, 0x1f, 0x8f, 0xbc, 0x94, 0x6c, 0x41, 0xd7, 0x8b, 0xec, 0xa1, - 0x15, 0x85, 0xa1, 0xaf, 0x98, 0x75, 0x05, 0xd4, 0x92, 0x5e, 0xac, 0x5b, 0xaf, 0x0f, 0xc3, 0xd0, - 0xd7, 0xac, 0x3a, 0xdc, 0x20, 0x95, 0xe4, 0x21, 0x90, 0xcd, 0x9d, 0x52, 0x08, 0xcd, 0x44, 0x43, - 0x20, 0x8b, 0x23, 0x58, 0x4e, 0x68, 0x7c, 0xe1, 0x39, 0xd4, 0xb2, 0x1d, 0x27, 0x1c, 0xa5, 0x73, - 0x62, 0x41, 0x00, 0xdd, 0x45, 0xa0, 0x23, 0xa9, 0xb4, 0x25, 0x75, 0x34, 0xa3, 0xc5, 0xa4, 0x44, - 0x5e, 0x06, 0x8a, 0xec, 0x16, 0x6f, 0x00, 0xd5, 0x1c, 0x0b, 0xa0, 0xc8, 0x74, 0x1b, 0xba, 0x81, - 0x3d, 0xa4, 0x49, 0x64, 0x3b, 0x7a, 0x6b, 0x5a, 0x12, 0x70, 0xcb, 0x08, 0xb7, 0xaf, 0xaa, 0x35, - 0xbd, 0xf9, 0x20, 0x2f, 0xca, 0x83, 0x20, 0xa7, 0xe5, 0x72, 0x10, 0x4d, 0x27, 0x05, 0x41, 0x26, - 0xcf, 0xa1, 0x15, 0x87, 0x23, 0xa6, 0x59, 0xac, 0xe4, 0xb6, 0x58, 0x93, 0x57, 0xa5, 0x9b, 0x7c, - 0x9c, 0x16, 0x53, 0x43, 0x6c, 0xb9, 0x37, 0x6e, 0x98, 0xee, 0xcd, 0x71, 0x5a, 0x24, 0xdb, 0xd0, - 0xbc, 0x60, 0x34, 0x52, 0x0d, 0xae, 0x0a, 0xbb, 0x87, 0x68, 0xf7, 0xe6, 0x0f, 0x5e, 0x6d, 0xed, - 0x1f, 0x8f, 0x82, 0x80, 0xfa, 0x63, 0x2b, 0x16, 0xb8, 0x99, 0xee, 0xbb, 0x04, 0xc1, 0xc6, 0xd7, - 0xde, 0x05, 0xa2, 0xa9, 0x08, 0x10, 0x64, 0xf2, 0x4b, 0x58, 0xbd, 0xf4, 0x62, 0x7a, 0x36, 0xb2, - 0xe3, 0xf1, 0x6d, 0xe4, 0xae, 0x80, 0xbc, 0xaf, 0xd6, 0xba, 0xd2, 0x1b, 0x63, 0xb5, 0x72, 0x59, - 0x5e, 0x35, 0x01, 0x1d, 0x09, 0xdf, 0xbb, 0x19, 0x5d, 0xd3, 0x1d, 0x47, 0x47, 0xee, 0x3f, 0x40, - 0xef, 0xcc, 0x0f, 0x4f, 0x6c, 0xdf, 0x3a, 0x39, 0x8b, 0xac, 0xfc, 0xb6, 0xb2, 0x2e, 0xc0, 0xef, - 0x21, 0xf8, 0x37, 0x42, 0xed, 0xe5, 0x37, 0x87, 0x85, 0xfd, 0x65, 0x49, 0xda, 0xbf, 0x3c, 0x8b, - 0xb2, 0x15, 0xe4, 0x67, 0xd0, 0xa6, 0x81, 0x63, 0x47, 0xc9, 0xc8, 0xb7, 0x99, 0x17, 0x06, 0xbd, - 0xfb, 0x02, 0x6d, 0x11, 0xd1, 0x76, 0xb3, 0x75, 0x7b, 0x53, 0x66, 0x5e, 0x99, 0xfc, 0x3e, 0x74, - 0xd4, 0x6a, 0x41, 0x32, 0x0f, 0x72, 0xe6, 0xb8, 0x4a, 0x34, 0x89, 0x76, 0x92, 0x15, 0x64, 0xcd, - 0xd1, 0x51, 0x0f, 0xcb, 0xcc, 0xb5, 0x7b, 0x94, 0x39, 0x3a, 0xc5, 0x81, 0x7b, 0x25, 0x2e, 0xbf, - 0xe8, 0x2b, 0x2e, 0x1f, 0xe4, 0xa6, 0xc9, 0x98, 0xd7, 0xdf, 0xf4, 0x35, 0xaf, 0xd5, 0xcb, 0x49, - 0x95, 0x93, 0x1b, 0x41, 0xc6, 0xc6, 0xbb, 0x1a, 0xd1, 0xec, 0xcb, 0x1a, 0xc1, 0x9e, 0x1c, 0xc3, - 0x4a, 0x7e, 0x7f, 0x4e, 0x3b, 0xf1, 0x28, 0xb7, 0xed, 0x64, 0xb7, 0xe8, 0x0c, 0xff, 0xc5, 0xf3, - 0x12, 0x79, 0x29, 0x2a, 0xb2, 0xfe, 0xf0, 0x06, 0xd4, 0x74, 0x33, 0x3b, 0x2f, 0x91, 0xbf, 0x6c, - 0xc0, 0x5c, 0x64, 0x5f, 0xf3, 0xf3, 0xce, 0xf8, 0xab, 0x59, 0x68, 0x7f, 0x1d, 0x87, 0xc3, 0x1b, - 0xe3, 0xd2, 0x7a, 0x69, 0x5c, 0x7a, 0x08, 0x4b, 0x51, 0x1c, 0x3a, 0x34, 0x49, 0xac, 0x84, 0xd9, - 0x6c, 0x94, 0xe4, 0xe3, 0x46, 0x15, 0x60, 0x1d, 0x4a, 0x9d, 0x23, 0xa1, 0x92, 0x86, 0x6c, 0xd1, - 0xb8, 0x98, 0xfc, 0x11, 0xdc, 0xcd, 0xc7, 0x1c, 0x79, 0x5c, 0x19, 0x4c, 0x3e, 0x28, 0x09, 0x3d, - 0x0a, 0xe0, 0xbd, 0xf3, 0x09, 0x75, 0x13, 0x5b, 0x40, 0x9f, 0xce, 0xbe, 0xa3, 0x05, 0xed, 0xd7, - 0x92, 0x16, 0x70, 0x1e, 0xf8, 0xf0, 0x60, 0x3c, 0x1a, 0xc9, 0xf7, 0x43, 0x06, 0xa0, 0x8f, 0x26, - 0x04, 0x25, 0x85, 0xbe, 0xdc, 0xbb, 0xbc, 0xa1, 0xfe, 0xc6, 0xd6, 0xb0, 0x4f, 0x73, 0xb7, 0x68, - 0x4d, 0xf7, 0x6b, 0x42, 0x6b, 0xd8, 0xb7, 0x37, 0x90, 0xee, 0x6e, 0x85, 0x3e, 0x35, 0x72, 0x3b, - 0x98, 0x5e, 0x43, 0x85, 0xce, 0x2c, 0x5d, 0x96, 0x55, 0x64, 0xe7, 0xe3, 0xaf, 0x2b, 0xd0, 0xca, - 0xed, 0x6e, 0xcf, 0xa1, 0x26, 0xf7, 0xca, 0x5e, 0xe5, 0xe1, 0x74, 0x66, 0x70, 0xb2, 0x4a, 0x58, - 0xd8, 0x0d, 0x58, 0x7c, 0x6d, 0xa2, 0xfa, 0xda, 0x0b, 0x68, 0x66, 0xc4, 0xa4, 0x0b, 0xd3, 0x6f, - 0xe9, 0xb5, 0xc8, 0xa0, 0x1a, 0x26, 0xff, 0x49, 0x16, 0x61, 0xf6, 0xc2, 0xf6, 0x47, 0x32, 0x4d, - 0x6a, 0x98, 0xb2, 0xf0, 0x65, 0xf5, 0xa7, 0x15, 0xa3, 0x0e, 0x35, 0x99, 0x5b, 0x19, 0x7f, 0x57, - 0x81, 0x66, 0x26, 0x6f, 0x22, 0x1d, 0xa8, 0x7a, 0x2e, 0x82, 0x54, 0x3d, 0x97, 0xf4, 0x60, 0x6e, - 0x48, 0xf9, 0x6a, 0x48, 0x7a, 0xd5, 0x87, 0xd3, 0x1b, 0x0d, 0x53, 0x15, 0xc9, 0x13, 0x98, 0x61, - 0xd7, 0x91, 0x5c, 0x0c, 0x1d, 0xed, 0x98, 0x0c, 0x96, 0xfc, 0x7d, 0x7c, 0x1d, 0x51, 0x53, 0x68, - 0x1a, 0x9f, 0x41, 0x43, 0x8b, 0x48, 0x0d, 0xaa, 0x83, 0xc3, 0xee, 0x14, 0x99, 0xe7, 0xed, 0x5b, - 0x5b, 0xfb, 0x3b, 0xd6, 0xe1, 0x81, 0x79, 0xdc, 0xad, 0x90, 0x39, 0x98, 0xde, 0xdf, 0x3d, 0xee, - 0x56, 0x8d, 0x08, 0xba, 0xc5, 0x94, 0x6c, 0x8c, 0xde, 0x23, 0x68, 0xdb, 0xae, 0x4b, 0x5d, 0x2b, - 0x4f, 0xb2, 0x25, 0x84, 0xaf, 0x91, 0xe9, 0xc7, 0x30, 0x2f, 0xa7, 0x4a, 0xaa, 0x36, 0x2d, 0xd4, - 0x3a, 0x28, 0x46, 0x45, 0x63, 0x1d, 0x7d, 0x81, 0xb3, 0xa1, 0xd0, 0x98, 0x61, 0xc3, 0x42, 0x49, - 0x7a, 0x46, 0x1e, 0x6a, 0xb5, 0xe6, 0x66, 0x37, 0xdd, 0x13, 0xb8, 0xc6, 0x60, 0x47, 0xb0, 0xdc, - 0x80, 0x39, 0x4c, 0xd1, 0x30, 0x63, 0xed, 0xe4, 0xd5, 0x4c, 0x55, 0x6d, 0x3c, 0x2f, 0x34, 0x81, - 0x4c, 0xde, 0xd9, 0x84, 0xf1, 0x00, 0x1a, 0x5a, 0x40, 0x08, 0xcc, 0xf0, 0xa0, 0x0a, 0xa9, 0x8b, - 0xdf, 0x46, 0x08, 0x73, 0xa8, 0x40, 0x9e, 0x40, 0xdb, 0x0b, 0x4e, 0xc2, 0x51, 0xe0, 0x5a, 0xf1, - 0xc8, 0xa7, 0x09, 0x4e, 0xbc, 0xa6, 0x0a, 0x94, 0x46, 0x3e, 0x35, 0x5b, 0xa8, 0xc1, 0x0b, 0x09, - 0xd9, 0x84, 0x4e, 0x38, 0x62, 0x59, 0x93, 0xea, 0xb8, 0x49, 0x5b, 0xa9, 0x08, 0x1b, 0xe3, 0x97, - 0x40, 0xc6, 0x33, 0x45, 0xf2, 0x20, 0xd3, 0x93, 0x79, 0xd5, 0x13, 0xa1, 0x80, 0xbe, 0xfa, 0x08, - 0x6a, 0x32, 0x5b, 0x44, 0x57, 0xb5, 0x73, 0x4a, 0x26, 0x56, 0x1a, 0xcf, 0xf2, 0xe8, 0xe8, 0xa7, - 0x77, 0xa1, 0x1b, 0x9b, 0x50, 0x57, 0x65, 0xee, 0x25, 0xe6, 0xd1, 0x58, 0x79, 0x89, 0xff, 0xd6, - 0x9e, 0xab, 0x66, 0x3c, 0xf7, 0xaf, 0x15, 0xa8, 0x49, 0x23, 0x72, 0x0f, 0x1a, 0x3a, 0x5a, 0x15, - 0x7b, 0x69, 0xc3, 0x4c, 0x05, 0xff, 0x3f, 0x7e, 0xe5, 0x1c, 0x46, 0x01, 0x8b, 0x6d, 0xe7, 0x2d, - 0x75, 0xc5, 0xe2, 0xab, 0x9b, 0xa9, 0x80, 0xac, 0x42, 0x3d, 0x8a, 0xa9, 0xe5, 0x06, 0x36, 0x13, - 0xc7, 0x49, 0x9d, 0xcf, 0x2d, 0xba, 0x13, 0xd8, 0xcc, 0xf8, 0x87, 0x2e, 0xcc, 0x70, 0x08, 0xb2, - 0x0c, 0x35, 0x9e, 0x5e, 0x87, 0x01, 0x76, 0x1d, 0x4b, 0xe4, 0x73, 0x00, 0x2f, 0xb2, 0x2e, 0x68, - 0x9c, 0xf0, 0xba, 0xaa, 0x58, 0xd7, 0x5d, 0xbd, 0xae, 0xdf, 0x48, 0xb9, 0xd9, 0xf0, 0x22, 0xfc, - 0x49, 0x7e, 0x87, 0x37, 0x16, 0xb2, 0xd0, 0x09, 0x7d, 0x3c, 0x13, 0xe7, 0xd3, 0xc9, 0x29, 0xc4, - 0xa6, 0x56, 0x20, 0x2b, 0x30, 0x97, 0xc4, 0x8e, 0x15, 0x50, 0x4e, 0x8c, 0xaf, 0xbe, 0x5a, 0x12, - 0x3b, 0xfb, 0x94, 0x91, 0xcf, 0xa0, 0xc1, 0x2b, 0xa2, 0x30, 0x66, 0x49, 0x6f, 0x56, 0xf4, 0x5f, - 0xcf, 0xf1, 0x30, 0x66, 0xa6, 0x1d, 0x9c, 0x51, 0xb3, 0x9e, 0xc4, 0x0e, 0x2f, 0x25, 0xe4, 0x39, - 0xac, 0x0a, 0x1c, 0x7b, 0x48, 0x5d, 0x61, 0x64, 0x79, 0x91, 0x95, 0x50, 0x66, 0x79, 0x6e, 0xd2, - 0x6b, 0x09, 0xe4, 0x45, 0x8e, 0xcc, 0xeb, 0xb9, 0xc5, 0x20, 0x3a, 0xa2, 0x6c, 0xe0, 0x26, 0x9c, - 0x80, 0x9b, 0x30, 0x41, 0xa0, 0x26, 0x09, 0xb8, 0x09, 0x43, 0x02, 0xbc, 0x42, 0x12, 0x98, 0x9b, - 0x44, 0xc0, 0x4d, 0x98, 0x26, 0x20, 0x70, 0x4a, 0x09, 0xb4, 0x25, 0x01, 0x8e, 0x3c, 0x46, 0x60, - 0x1d, 0x1a, 0x9e, 0x33, 0x8c, 0x2c, 0xb1, 0x6d, 0xf2, 0x90, 0x63, 0x76, 0x6f, 0xca, 0xac, 0x73, - 0x91, 0xd8, 0x11, 0xbf, 0x82, 0x8e, 0xae, 0xb6, 0x9c, 0xd0, 0x55, 0x67, 0x8e, 0x4a, 0x9d, 0x06, - 0xa8, 0xb8, 0x15, 0xb8, 0xdb, 0xa1, 0x2b, 0xf2, 0x71, 0x65, 0xcb, 0xcb, 0xe4, 0x11, 0x74, 0xb8, - 0x63, 0x32, 0x64, 0x40, 0x90, 0x69, 0x26, 0xb1, 0xa3, 0x39, 0x3c, 0x82, 0x0e, 0x27, 0x9f, 0x51, - 0x6a, 0x4a, 0x25, 0x37, 0x49, 0x89, 0xfe, 0x04, 0x16, 0x50, 0x49, 0x74, 0x4f, 0x69, 0xce, 0x0b, - 0xcd, 0x79, 0xa1, 0xc9, 0x3b, 0x86, 0xda, 0x9b, 0xd0, 0x0a, 0x42, 0x66, 0xe9, 0x99, 0x70, 0x5a, - 0x3e, 0x13, 0x9a, 0x41, 0xc8, 0x54, 0x81, 0xdc, 0x07, 0x5e, 0xb4, 0xd4, 0x84, 0x38, 0x13, 0xc8, - 0x8d, 0x20, 0x64, 0x47, 0x72, 0x4e, 0x3c, 0x85, 0xb6, 0xaa, 0x97, 0xc3, 0x72, 0x3e, 0x61, 0x58, - 0x9a, 0xd2, 0x46, 0x8e, 0x0c, 0xa2, 0xaa, 0x51, 0xf6, 0x34, 0xea, 0x8e, 0x1c, 0x68, 0x44, 0x4d, - 0x07, 0xfb, 0x8f, 0x6f, 0x40, 0xdd, 0x51, 0xe3, 0xfd, 0xa1, 0xb4, 0x4a, 0x87, 0xee, 0xad, 0x18, - 0xba, 0x8a, 0xd0, 0x52, 0x83, 0x42, 0x76, 0x81, 0xe4, 0xb4, 0xe4, 0x08, 0xfa, 0x37, 0x8e, 0x60, - 0xc5, 0x9c, 0xcf, 0x40, 0x88, 0x41, 0xfc, 0x54, 0xc2, 0x14, 0x06, 0x72, 0x28, 0x8f, 0x2b, 0xd9, - 0x57, 0x3d, 0x4c, 0xa8, 0x5b, 0x18, 0xcf, 0x40, 0xeb, 0xee, 0x64, 0x86, 0xf4, 0x2b, 0x58, 0xd7, - 0x0e, 0x2f, 0x9d, 0xb8, 0x91, 0x30, 0x5b, 0xc1, 0x21, 0x18, 0x9b, 0xbb, 0x68, 0x3f, 0x79, 0xe2, - 0xff, 0xa8, 0xed, 0x77, 0xca, 0xe6, 0xfe, 0x26, 0x2c, 0x85, 0xb1, 0x77, 0xe6, 0x05, 0xb6, 0x2f, - 0x48, 0x24, 0xd4, 0xa7, 0x0e, 0x0b, 0xe3, 0x5e, 0x2c, 0xb6, 0xa0, 0x05, 0x55, 0x79, 0x14, 0x3b, - 0x47, 0x58, 0x95, 0xb3, 0xe1, 0x0d, 0x6b, 0x9b, 0x24, 0x6f, 0xb3, 0x93, 0x30, 0x6d, 0xb3, 0x0b, - 0x0f, 0x72, 0xed, 0xa4, 0xd7, 0x11, 0xda, 0x9a, 0x09, 0xeb, 0x7b, 0x99, 0x16, 0xf5, 0xa5, 0x44, - 0x29, 0x8c, 0xea, 0x73, 0x01, 0x66, 0x94, 0x87, 0xc1, 0x5e, 0xe7, 0x61, 0x5e, 0xc0, 0xaa, 0x86, - 0x51, 0xee, 0xd7, 0x00, 0x17, 0x02, 0x60, 0x59, 0x29, 0xec, 0x0b, 0xcf, 0x4f, 0x34, 0xcd, 0x39, - 0xe0, 0x72, 0xcc, 0x34, 0xeb, 0x83, 0xdf, 0x85, 0xc5, 0x82, 0xaf, 0x45, 0x46, 0xda, 0xfb, 0x8d, - 0xdc, 0xee, 0x49, 0xce, 0xd7, 0xa2, 0x8a, 0xec, 0xc0, 0xfd, 0x32, 0x93, 0xb4, 0xdf, 0xbd, 0x3f, - 0x97, 0xc6, 0x77, 0xc7, 0x8d, 0x75, 0xb7, 0x73, 0x0d, 0x4b, 0xbe, 0xb2, 0xe1, 0x5f, 0x17, 0x1a, - 0x16, 0x64, 0xc7, 0x1b, 0xce, 0x98, 0x64, 0x1a, 0xfe, 0xb3, 0x42, 0xc3, 0xa9, 0x71, 0xda, 0xf0, - 0xf7, 0xf2, 0x4c, 0x28, 0xde, 0x8a, 0x0d, 0x6d, 0xe6, 0x9c, 0xf7, 0xae, 0x72, 0xd9, 0x5a, 0xfe, - 0x52, 0xec, 0x35, 0xd7, 0x30, 0x97, 0x13, 0xdd, 0x99, 0xac, 0x9c, 0xc3, 0x66, 0x39, 0xe5, 0x61, - 0xaf, 0xdf, 0x0d, 0xeb, 0x6a, 0xaa, 0x39, 0xd8, 0xcf, 0x01, 0xce, 0x19, 0x8b, 0x10, 0xe7, 0x57, - 0xb9, 0xa8, 0x6e, 0xef, 0xf8, 0xf8, 0x50, 0x5a, 0x37, 0xb8, 0x8e, 0x32, 0xa8, 0xab, 0xfc, 0xb8, - 0xf7, 0x27, 0xb9, 0x0b, 0x5a, 0x7e, 0x9e, 0xeb, 0x8b, 0x4f, 0xad, 0xc4, 0xa3, 0x76, 0x1e, 0x4e, - 0x58, 0x9e, 0xdb, 0xfb, 0x2d, 0x9e, 0xf1, 0xbc, 0x3c, 0x70, 0x5f, 0xd6, 0x60, 0x86, 0x6f, 0x51, - 0x2f, 0x01, 0xea, 0x6a, 0xbb, 0xfa, 0xb6, 0x56, 0xff, 0xb7, 0x4a, 0xf7, 0xb7, 0x15, 0x13, 0xfc, - 0xf0, 0xcc, 0x8a, 0x62, 0x7a, 0xea, 0x5d, 0x19, 0xdf, 0xc0, 0x42, 0x19, 0xf5, 0x35, 0xa8, 0xeb, - 0x49, 0x28, 0x81, 0x75, 0x99, 0xa7, 0x1b, 0x62, 0xd4, 0x30, 0x06, 0x97, 0x05, 0xe3, 0xef, 0x2b, - 0xd0, 0xd0, 0x9d, 0x92, 0xe9, 0x04, 0x3b, 0x0f, 0x5d, 0x19, 0x1c, 0x89, 0x74, 0x42, 0x14, 0xc9, - 0x13, 0x98, 0x8d, 0x6c, 0x76, 0xae, 0x22, 0xa0, 0xb5, 0xa2, 0x3f, 0x1e, 0x1f, 0xda, 0xec, 0x5c, - 0x7a, 0x46, 0x2a, 0xae, 0x7d, 0x07, 0x0d, 0x2d, 0x23, 0xcb, 0x30, 0x4b, 0xaf, 0x6c, 0x87, 0x49, - 0x56, 0x7b, 0x53, 0xa6, 0x2c, 0x92, 0x1e, 0xd4, 0x64, 0x8f, 0x64, 0x48, 0xb7, 0x37, 0x65, 0x62, - 0xf9, 0x65, 0x0b, 0x80, 0xe3, 0xc8, 0x51, 0x30, 0xfe, 0xb6, 0x02, 0xad, 0xac, 0x33, 0xc9, 0xd7, - 0xd0, 0xb4, 0x83, 0x20, 0x64, 0xe2, 0x12, 0x49, 0x85, 0x72, 0x1f, 0x96, 0xb8, 0xfd, 0xf1, 0x56, - 0xaa, 0x26, 0x13, 0xb4, 0xac, 0xe1, 0xda, 0x57, 0xd0, 0x2d, 0x2a, 0xbc, 0x57, 0xaa, 0xf6, 0x02, - 0xe6, 0x0b, 0xc7, 0x86, 0x08, 0x5c, 0xf9, 0x39, 0xc4, 0xed, 0x67, 0x65, 0x6e, 0xc5, 0x65, 0xe2, - 0xc0, 0xa9, 0x4a, 0x19, 0xff, 0x6d, 0xbc, 0x82, 0xba, 0x3e, 0x70, 0x7b, 0x50, 0xc3, 0xbb, 0x8e, - 0x0a, 0x06, 0x1e, 0x58, 0x26, 0x8b, 0xd9, 0x90, 0x77, 0x6f, 0x4a, 0x06, 0xbd, 0x2f, 0xbb, 0xd0, - 0x91, 0xf5, 0x56, 0x18, 0x8b, 0xc5, 0x68, 0x3c, 0x83, 0x86, 0x3e, 0x20, 0x39, 0xdf, 0x53, 0x2f, - 0x4e, 0x18, 0x72, 0x90, 0x05, 0x4e, 0xc2, 0xb7, 0x13, 0xa6, 0x48, 0xf0, 0xdf, 0xc6, 0x5f, 0x57, - 0x80, 0x14, 0x73, 0xf2, 0xc1, 0x0e, 0xcf, 0xc9, 0xc2, 0xd8, 0x39, 0xa7, 0x09, 0x8b, 0x6d, 0x16, - 0xc6, 0x7c, 0xa6, 0xca, 0xae, 0x77, 0xb2, 0xe2, 0x81, 0x4b, 0x1e, 0x40, 0x53, 0x5f, 0x00, 0x78, - 0x32, 0xe0, 0x6d, 0x98, 0xa0, 0x44, 0x52, 0x41, 0x5f, 0x0c, 0x78, 0xae, 0x08, 0x7a, 0x1b, 0x26, - 0x28, 0xd1, 0xc0, 0xfd, 0x76, 0xa6, 0x5e, 0xe9, 0x56, 0xcd, 0xfa, 0x79, 0x98, 0x30, 0xd1, 0x91, - 0x2b, 0x58, 0x2e, 0xff, 0x04, 0x43, 0x3e, 0xc9, 0xa4, 0x0f, 0xab, 0x13, 0xee, 0x13, 0x30, 0x4d, - 0xf9, 0x02, 0xea, 0xaa, 0x09, 0xbc, 0x54, 0x59, 0x99, 0xf4, 0x0d, 0x46, 0x2b, 0x1a, 0xff, 0x35, - 0x0d, 0xdd, 0x62, 0x35, 0x77, 0x65, 0xc2, 0x6c, 0xa6, 0xb2, 0x35, 0x59, 0x28, 0x4b, 0x44, 0xf8, - 0xb4, 0x19, 0xda, 0x0e, 0xba, 0x80, 0xff, 0xe4, 0x7d, 0x57, 0xdf, 0xfe, 0xf8, 0x19, 0x2c, 0xe3, - 0x6a, 0x40, 0x11, 0x3f, 0x76, 0xef, 0x42, 0xc3, 0x8b, 0x2e, 0x9e, 0xf2, 0x70, 0x48, 0xc6, 0xd6, - 0x0d, 0xb3, 0xce, 0x05, 0xfb, 0x94, 0xa9, 0xca, 0xbe, 0xac, 0xac, 0xe9, 0xca, 0xbe, 0xa8, 0xfc, - 0x08, 0x66, 0x79, 0x46, 0xa4, 0x02, 0x62, 0x15, 0xce, 0x1d, 0x7b, 0x34, 0x1e, 0x04, 0xa7, 0xa1, - 0x29, 0x6b, 0xc9, 0x27, 0x50, 0x97, 0x0d, 0xd8, 0xac, 0x57, 0x17, 0x9a, 0x1d, 0x7d, 0xd3, 0xcf, - 0x84, 0xe2, 0x9c, 0x68, 0xcf, 0x66, 0xa8, 0xda, 0x17, 0xaa, 0x8d, 0x89, 0xaa, 0x7d, 0xae, 0xba, - 0x05, 0xeb, 0xb6, 0xef, 0x87, 0x97, 0x56, 0x12, 0x85, 0xe1, 0x29, 0x75, 0xad, 0x24, 0x1c, 0xc5, - 0x0e, 0xc5, 0xcd, 0x89, 0xaa, 0xc8, 0x76, 0x4d, 0x28, 0x1d, 0x49, 0x9d, 0x23, 0xa1, 0x72, 0x88, - 0x1a, 0xe4, 0xdb, 0xfc, 0xfa, 0x6d, 0x8a, 0x06, 0x37, 0x26, 0x8c, 0xd1, 0xff, 0xf1, 0x1a, 0xde, - 0x1e, 0x9f, 0x71, 0x98, 0xb0, 0xde, 0x7e, 0xc6, 0x19, 0x5b, 0xd0, 0xc9, 0xde, 0xd7, 0x0d, 0x76, - 0x8a, 0x33, 0xbf, 0xfa, 0xce, 0x99, 0xef, 0x03, 0x19, 0xff, 0x3c, 0x4a, 0x3e, 0xca, 0x70, 0x58, - 0x2a, 0xb9, 0x19, 0xc4, 0x19, 0xff, 0x79, 0x66, 0xc6, 0x4f, 0xe7, 0x0e, 0xa1, 0xdc, 0x37, 0xd2, - 0x74, 0xb6, 0xff, 0x67, 0x15, 0x5a, 0xd9, 0xaa, 0xb2, 0x6b, 0x89, 0xe2, 0x0c, 0xae, 0x8e, 0xcd, - 0x60, 0x3d, 0x0f, 0xa7, 0x6f, 0x9c, 0x87, 0x3f, 0x85, 0x79, 0x9d, 0x04, 0x5b, 0xd2, 0xa0, 0x56, - 0x6e, 0xd0, 0xd1, 0x7a, 0xc7, 0xc2, 0xf2, 0x19, 0x74, 0x54, 0xc6, 0x6c, 0xdd, 0x38, 0xe3, 0x5b, - 0x98, 0x48, 0x4b, 0xb3, 0xa7, 0xd0, 0x3e, 0x0d, 0xe3, 0x4b, 0x3b, 0x56, 0xcd, 0xd5, 0x27, 0x58, - 0xa1, 0x96, 0xb4, 0x7a, 0x0c, 0x0b, 0xf4, 0x2a, 0xa2, 0x0e, 0xa3, 0xae, 0x25, 0xd6, 0x8d, 0xed, - 0xba, 0xb1, 0x5a, 0xb8, 0x77, 0x54, 0xd5, 0x20, 0xba, 0x78, 0xba, 0xc5, 0x2b, 0x8a, 0xfa, 0x7d, - 0xd4, 0x9f, 0x1d, 0xd3, 0xef, 0x0b, 0x7d, 0xe3, 0xf7, 0xf2, 0x23, 0x8c, 0xb3, 0xec, 0x76, 0x23, - 0x6c, 0xc4, 0x50, 0x57, 0xb4, 0x4b, 0xc7, 0xea, 0x13, 0xe8, 0x7a, 0xc1, 0x59, 0x4c, 0x93, 0x44, - 0x7e, 0xd0, 0xf7, 0xf4, 0x59, 0x3f, 0x8f, 0xf2, 0x43, 0x14, 0xf3, 0xed, 0x9d, 0x16, 0x34, 0xf1, - 0xca, 0x8d, 0xe6, 0x14, 0x8d, 0xe7, 0x30, 0x87, 0xab, 0x9f, 0x2c, 0x41, 0x8d, 0x5e, 0xf1, 0x9c, - 0x42, 0xed, 0x84, 0xf4, 0x8a, 0x0d, 0x22, 0x2e, 0x16, 0x13, 0x3c, 0x52, 0xeb, 0x8a, 0x13, 0x8e, - 0x0c, 0x13, 0x16, 0x4a, 0x2e, 0xde, 0xc9, 0x23, 0x68, 0x7b, 0x49, 0x68, 0x31, 0x6f, 0x48, 0x13, - 0x66, 0x0f, 0x15, 0x56, 0xcb, 0x4b, 0xc2, 0x63, 0x25, 0x23, 0xcb, 0x50, 0x1b, 0x45, 0x5c, 0x45, - 0x40, 0x56, 0x4c, 0x2c, 0x19, 0x11, 0xf4, 0x26, 0x5d, 0xba, 0xdf, 0x76, 0x95, 0x7c, 0x06, 0x35, - 0x79, 0x6f, 0x8c, 0xd7, 0x57, 0x4b, 0xfa, 0x23, 0x55, 0xee, 0xba, 0x19, 0x95, 0x8c, 0x0d, 0xe8, - 0xe4, 0x6b, 0x38, 0x37, 0x04, 0xc0, 0xc0, 0x0d, 0x35, 0xb7, 0xca, 0xb8, 0xbd, 0xdf, 0xf8, 0x5e, - 0xc1, 0xbd, 0x9b, 0xee, 0xe2, 0xdf, 0xe7, 0xf8, 0x7b, 0xcf, 0x6e, 0x0e, 0x26, 0xb5, 0xfc, 0xfe, - 0xdb, 0xe0, 0x19, 0x2c, 0x95, 0x5e, 0xbe, 0x93, 0x75, 0x80, 0x68, 0x74, 0xe2, 0x7b, 0x8e, 0x95, - 0xee, 0xcb, 0x0d, 0x29, 0xf9, 0x8e, 0x5e, 0xbf, 0xf7, 0xe5, 0x96, 0xf1, 0x5a, 0x2e, 0xa5, 0xc2, - 0x2b, 0x85, 0x35, 0xd0, 0xdb, 0xa9, 0x0a, 0x80, 0x55, 0x59, 0x1f, 0xb6, 0x7c, 0x8d, 0xe2, 0x64, - 0x15, 0x87, 0x23, 0x5f, 0x9a, 0x45, 0x38, 0xec, 0xf8, 0xff, 0x18, 0xee, 0x00, 0x16, 0xcb, 0xbe, - 0xb3, 0xdd, 0x02, 0xb0, 0x5f, 0x04, 0xec, 0x97, 0x03, 0xde, 0x9a, 0xe1, 0x04, 0xc0, 0x5d, 0xe8, - 0xe4, 0x5f, 0x58, 0x94, 0x5c, 0xde, 0xcf, 0x44, 0x61, 0xe8, 0xe3, 0x14, 0x9a, 0x2f, 0xbe, 0xa9, + // 3971 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7b, 0x4b, 0x73, 0x1c, 0xb7, + 0x76, 0x3f, 0x67, 0x48, 0x0e, 0x67, 0xce, 0x3c, 0x38, 0x02, 0x5f, 0x43, 0x4a, 0x94, 0xe4, 0x96, + 0x5d, 0xa6, 0xfd, 0xbf, 0x96, 0xf5, 0xa7, 0xa5, 0xd1, 0x95, 0x73, 0xe3, 0x5b, 0x14, 0x49, 0x9b, + 0x63, 0x4b, 0x24, 0xab, 0x49, 0xcb, 0xb9, 0xa9, 0x5b, 0xd5, 0x69, 0x76, 0x83, 0x64, 0x47, 0x3d, + 0xdd, 0xed, 0x6e, 0x0c, 0x1f, 0x37, 0xab, 0xdc, 0xdc, 0x2c, 0x52, 0xa9, 0x54, 0x16, 0xa9, 0x4a, + 0x65, 0x95, 0x55, 0x56, 0xa9, 0x7c, 0x83, 0x2c, 0x92, 0x4d, 0xaa, 0x72, 0xbf, 0x4a, 0x76, 0x59, + 0x64, 0x9f, 0x02, 0x70, 0x80, 0x7e, 0x4c, 0x0f, 0x45, 0xe5, 0xb5, 0xe2, 0xe0, 0xe0, 0x9c, 0x1f, + 0x7e, 0x00, 0x0e, 0x80, 0x73, 0xd0, 0x20, 0x90, 0x53, 0xea, 0x7b, 0x57, 0x27, 0xb6, 0xf3, 0x96, + 0x06, 0xee, 0xe3, 0x28, 0x0e, 0x59, 0x48, 0x66, 0x85, 0xcc, 0x68, 0x43, 0xf3, 0xe8, 0x3a, 0x70, + 0x4c, 0xfa, 0xe3, 0x88, 0x26, 0xcc, 0xf8, 0xab, 0x25, 0x68, 0x1e, 0x87, 0x3b, 0x36, 0xb3, 0x23, + 0xdf, 0x0e, 0x28, 0xf9, 0x18, 0xe6, 0x13, 0x5e, 0x15, 0x38, 0xd4, 0x0a, 0x46, 0xc3, 0x13, 0x1a, + 0xf7, 0xe6, 0x1f, 0x56, 0x36, 0x66, 0xcc, 0x8e, 0x12, 0xef, 0x0b, 0x29, 0xd9, 0x80, 0x39, 0x2f, + 0xb0, 0x92, 0xeb, 0xc0, 0xe9, 0x55, 0x1e, 0x56, 0x36, 0x9a, 0x9b, 0xed, 0xc7, 0xa2, 0x81, 0xc7, + 0x83, 0x80, 0xe3, 0xef, 0x4d, 0x99, 0x35, 0x4f, 0xfc, 0x22, 0xcf, 0xa1, 0xe5, 0x45, 0x09, 0x65, + 0xd6, 0x28, 0x72, 0x6d, 0x46, 0x7b, 0x55, 0xa1, 0x4e, 0x94, 0xfa, 0xe1, 0x11, 0x65, 0xdf, 0x8b, + 0x9a, 0xbd, 0x29, 0xb3, 0x29, 0x34, 0x65, 0x91, 0x7c, 0x03, 0x44, 0x1a, 0xba, 0xd4, 0x67, 0xb6, + 0x32, 0x9f, 0x16, 0xe6, 0x2b, 0x59, 0xf3, 0x1d, 0x5e, 0xaf, 0x31, 0xba, 0xc2, 0x28, 0x23, 0x4b, + 0x19, 0xc4, 0x74, 0x18, 0x5e, 0xd0, 0xde, 0xcc, 0x38, 0x03, 0x53, 0xd4, 0x68, 0x06, 0xb2, 0x48, + 0x0e, 0x61, 0xc9, 0x76, 0x98, 0x77, 0x41, 0xad, 0x28, 0x0e, 0x4f, 0x3d, 0x9f, 0x2a, 0x12, 0xb3, + 0x02, 0x61, 0x0d, 0x11, 0xb6, 0x84, 0xce, 0xa1, 0x54, 0xd1, 0x3c, 0x16, 0xec, 0x71, 0x71, 0x09, + 0x22, 0x72, 0xaa, 0x4d, 0x46, 0xd4, 0xdc, 0xf2, 0x88, 0xc8, 0xf1, 0x35, 0x2c, 0x2a, 0xc4, 0xd0, + 0xf7, 0x9c, 0x6b, 0x45, 0x71, 0x4e, 0x00, 0xae, 0xe6, 0x01, 0x85, 0x86, 0x66, 0x48, 0xec, 0x31, + 0xe9, 0x38, 0x1c, 0xf2, 0xab, 0x4f, 0x84, 0xd3, 0xf4, 0x72, 0x70, 0x29, 0xbb, 0xf3, 0x30, 0x61, + 0x16, 0x0d, 0xdc, 0x28, 0xf4, 0x02, 0xed, 0x04, 0x8d, 0x1c, 0xdc, 0x5e, 0x98, 0xb0, 0x5d, 0xd4, + 0x48, 0xd9, 0x9d, 0x8f, 0x49, 0xc7, 0xe1, 0x90, 0x1d, 0x4c, 0x84, 0x4b, 0xd9, 0x9d, 0x8f, 0x49, + 0xc9, 0x2f, 0xa0, 0x77, 0x19, 0xc6, 0x6f, 0xfd, 0xd0, 0x76, 0xc7, 0x18, 0x36, 0x05, 0xe4, 0x3a, + 0x42, 0xfe, 0x80, 0x6a, 0x63, 0x2c, 0x97, 0x2f, 0x4b, 0x6b, 0xca, 0xa1, 0x91, 0x6d, 0xeb, 0x46, + 0x68, 0xcd, 0x78, 0x0c, 0x1a, 0x59, 0x7f, 0x09, 0x6d, 0x27, 0x0c, 0x4e, 0xbd, 0x33, 0x45, 0xb5, + 0x2d, 0xf0, 0x16, 0x10, 0x6f, 0x5b, 0xd4, 0x69, 0x82, 0x2d, 0x27, 0x53, 0xd6, 0x03, 0x38, 0xa4, + 0xcc, 0x76, 0xed, 0x74, 0x55, 0x75, 0xc6, 0x06, 0xf0, 0x35, 0x6a, 0xe4, 0xe7, 0x23, 0x2f, 0x1d, + 0x87, 0xc3, 0x1e, 0x92, 0x89, 0x70, 0xf9, 0xf9, 0xc8, 0x4b, 0xc9, 0x16, 0x74, 0xbd, 0xc8, 0x1e, + 0x5a, 0x51, 0x18, 0xfa, 0x8a, 0x59, 0x57, 0x40, 0x2d, 0xe9, 0xc5, 0xba, 0xf5, 0xfa, 0x30, 0x0c, + 0x7d, 0xcd, 0xaa, 0xc3, 0x0d, 0x52, 0x49, 0x1e, 0x02, 0xd9, 0xdc, 0x29, 0x85, 0xd0, 0x4c, 0x34, + 0x04, 0xb2, 0x38, 0x82, 0xe5, 0x84, 0xc6, 0x17, 0x9e, 0x43, 0x2d, 0xdb, 0x71, 0xc2, 0x51, 0xea, + 0x13, 0x0b, 0x02, 0xe8, 0x2e, 0x02, 0x1d, 0x49, 0xa5, 0x2d, 0xa9, 0xa3, 0x19, 0x2d, 0x26, 0x25, + 0xf2, 0x32, 0x50, 0x64, 0xb7, 0x78, 0x03, 0xa8, 0xe6, 0x58, 0x00, 0x45, 0xa6, 0xdb, 0xd0, 0x0d, + 0xec, 0x21, 0x4d, 0x22, 0xdb, 0xd1, 0x5b, 0xd3, 0x92, 0x80, 0x5b, 0x46, 0xb8, 0x7d, 0x55, 0xad, + 0xe9, 0xcd, 0x07, 0x79, 0x51, 0x1e, 0x04, 0x39, 0x2d, 0x97, 0x83, 0x68, 0x3a, 0x29, 0x08, 0x32, + 0x79, 0x0e, 0xad, 0x38, 0x1c, 0x31, 0xcd, 0x62, 0x25, 0xb7, 0xc5, 0x9a, 0xbc, 0x2a, 0xdd, 0xe4, + 0xe3, 0xb4, 0x98, 0x1a, 0x62, 0xcb, 0xbd, 0x71, 0xc3, 0x74, 0x6f, 0x8e, 0xd3, 0x22, 0xd9, 0x86, + 0xe6, 0x05, 0xa3, 0x91, 0x6a, 0x70, 0x55, 0xd8, 0x3d, 0x44, 0xbb, 0x37, 0xbf, 0xf7, 0x6a, 0x6b, + 0xff, 0x78, 0x14, 0x04, 0xd4, 0x1f, 0x5b, 0xb1, 0xc0, 0xcd, 0x74, 0xdf, 0x25, 0x08, 0x36, 0xbe, + 0xf6, 0x2e, 0x10, 0x4d, 0x45, 0x80, 0x20, 0x93, 0x5f, 0xc2, 0xea, 0xa5, 0x17, 0xd3, 0xb3, 0x91, + 0x1d, 0x8f, 0x6f, 0x23, 0x77, 0x05, 0xe4, 0x7d, 0xb5, 0xd6, 0x95, 0xde, 0x18, 0xab, 0x95, 0xcb, + 0xf2, 0xaa, 0x09, 0xe8, 0x48, 0xf8, 0xde, 0xcd, 0xe8, 0x9a, 0xee, 0x38, 0x3a, 0x72, 0xff, 0x01, + 0x7a, 0x67, 0x7e, 0x78, 0x62, 0xfb, 0xd6, 0xc9, 0x59, 0x64, 0xe5, 0xb7, 0x95, 0x75, 0x01, 0x7e, + 0x0f, 0xc1, 0xbf, 0x11, 0x6a, 0x2f, 0xbf, 0x39, 0x2c, 0xec, 0x2f, 0x4b, 0xd2, 0xfe, 0xe5, 0x59, + 0x94, 0xad, 0x20, 0x3f, 0x83, 0x36, 0x0d, 0x1c, 0x3b, 0x4a, 0x46, 0xbe, 0xcd, 0xbc, 0x30, 0xe8, + 0xdd, 0x17, 0x68, 0x8b, 0x88, 0xb6, 0x9b, 0xad, 0xdb, 0x9b, 0x32, 0xf3, 0xca, 0xe4, 0x77, 0xa1, + 0xa3, 0x56, 0x0b, 0x92, 0x79, 0x90, 0x33, 0xc7, 0x55, 0xa2, 0x49, 0xb4, 0x93, 0xac, 0x20, 0x6b, + 0x8e, 0x03, 0xf5, 0xb0, 0xcc, 0x5c, 0x0f, 0x8f, 0x32, 0xc7, 0x41, 0x71, 0xe0, 0x5e, 0xc9, 0x90, + 0x5f, 0xf4, 0x15, 0x97, 0x0f, 0x72, 0x6e, 0x32, 0x36, 0xea, 0x6f, 0xfa, 0x9a, 0xd7, 0xea, 0xe5, + 0xa4, 0xca, 0xc9, 0x8d, 0x20, 0x63, 0xe3, 0x5d, 0x8d, 0x68, 0xf6, 0x65, 0x8d, 0x60, 0x4f, 0x8e, + 0x61, 0x25, 0xbf, 0x3f, 0xa7, 0x9d, 0x78, 0x94, 0xdb, 0x76, 0xb2, 0x5b, 0x74, 0x86, 0xff, 0xe2, + 0x79, 0x89, 0xbc, 0x14, 0x15, 0x59, 0x7f, 0x78, 0x03, 0x6a, 0xba, 0x99, 0x9d, 0x97, 0xc8, 0x5f, + 0x36, 0x60, 0x2e, 0xb2, 0xaf, 0xf9, 0x79, 0x67, 0xfc, 0xc5, 0x2c, 0xb4, 0xbf, 0x8e, 0xc3, 0xe1, + 0x8d, 0x71, 0x69, 0xbd, 0x34, 0x2e, 0x3d, 0x84, 0xa5, 0x28, 0x0e, 0x1d, 0x9a, 0x24, 0x56, 0xc2, + 0x6c, 0x36, 0x4a, 0xf2, 0x71, 0xa3, 0x0a, 0xb0, 0x0e, 0xa5, 0xce, 0x91, 0x50, 0x49, 0x43, 0xb6, + 0x68, 0x5c, 0x4c, 0xfe, 0x00, 0xee, 0xe6, 0x63, 0x8e, 0x3c, 0xae, 0x0c, 0x26, 0x1f, 0x94, 0x84, + 0x1e, 0x05, 0xf0, 0xde, 0xf9, 0x84, 0xba, 0x89, 0x2d, 0xe0, 0x98, 0xce, 0xbe, 0xa3, 0x05, 0x3d, + 0xae, 0x25, 0x2d, 0xa0, 0x1f, 0xf8, 0xf0, 0x60, 0x3c, 0x1a, 0xc9, 0xf7, 0x43, 0x06, 0xa0, 0x8f, + 0x26, 0x04, 0x25, 0x85, 0xbe, 0xdc, 0xbb, 0xbc, 0xa1, 0xfe, 0xc6, 0xd6, 0xb0, 0x4f, 0x73, 0xb7, + 0x68, 0x4d, 0xf7, 0x6b, 0x42, 0x6b, 0xd8, 0xb7, 0x37, 0x90, 0xee, 0x6e, 0x85, 0x3e, 0x35, 0x72, + 0x3b, 0x98, 0x5e, 0x43, 0x85, 0xce, 0x2c, 0x5d, 0x96, 0x55, 0x64, 0xfd, 0xf1, 0xd7, 0x15, 0x68, + 0xe5, 0x76, 0xb7, 0xe7, 0x50, 0x93, 0x7b, 0x65, 0xaf, 0xf2, 0x70, 0x3a, 0x33, 0x39, 0x59, 0x25, + 0x2c, 0xec, 0x06, 0x2c, 0xbe, 0x36, 0x51, 0x7d, 0xed, 0x05, 0x34, 0x33, 0x62, 0xd2, 0x85, 0xe9, + 0xb7, 0xf4, 0x5a, 0x64, 0x50, 0x0d, 0x93, 0xff, 0x24, 0x8b, 0x30, 0x7b, 0x61, 0xfb, 0x23, 0x99, + 0x26, 0x35, 0x4c, 0x59, 0xf8, 0xb2, 0xfa, 0xd3, 0x8a, 0x51, 0x87, 0x9a, 0xcc, 0xad, 0x8c, 0xbf, + 0xa9, 0x40, 0x33, 0x93, 0x37, 0x91, 0x0e, 0x54, 0x3d, 0x17, 0x41, 0xaa, 0x9e, 0x4b, 0x7a, 0x30, + 0x37, 0xa4, 0x7c, 0x35, 0x24, 0xbd, 0xea, 0xc3, 0xe9, 0x8d, 0x86, 0xa9, 0x8a, 0xe4, 0x09, 0xcc, + 0xb0, 0xeb, 0x48, 0x2e, 0x86, 0x8e, 0x1e, 0x98, 0x0c, 0x96, 0xfc, 0x7d, 0x7c, 0x1d, 0x51, 0x53, + 0x68, 0x1a, 0x9f, 0x41, 0x43, 0x8b, 0x48, 0x0d, 0xaa, 0x83, 0xc3, 0xee, 0x14, 0x99, 0xe7, 0xed, + 0x5b, 0x5b, 0xfb, 0x3b, 0xd6, 0xe1, 0x81, 0x79, 0xdc, 0xad, 0x90, 0x39, 0x98, 0xde, 0xdf, 0x3d, + 0xee, 0x56, 0x8d, 0x08, 0xba, 0xc5, 0x94, 0x6c, 0x8c, 0xde, 0x23, 0x68, 0xdb, 0xae, 0x4b, 0x5d, + 0x2b, 0x4f, 0xb2, 0x25, 0x84, 0xaf, 0x91, 0xe9, 0xc7, 0x30, 0x2f, 0x5d, 0x25, 0x55, 0x9b, 0x16, + 0x6a, 0x1d, 0x14, 0xa3, 0xa2, 0xb1, 0x8e, 0x63, 0x81, 0xde, 0x50, 0x68, 0xcc, 0xb0, 0x61, 0xa1, + 0x24, 0x3d, 0x23, 0x0f, 0xb5, 0x5a, 0x73, 0xb3, 0x9b, 0xee, 0x09, 0x5c, 0x63, 0xb0, 0x23, 0x58, + 0x6e, 0xc0, 0x1c, 0xa6, 0x68, 0x98, 0xb1, 0x76, 0xf2, 0x6a, 0xa6, 0xaa, 0x36, 0x9e, 0x17, 0x9a, + 0x40, 0x26, 0xef, 0x6c, 0xc2, 0x78, 0x00, 0x0d, 0x2d, 0x20, 0x04, 0x66, 0x78, 0x50, 0x85, 0xd4, + 0xc5, 0x6f, 0x23, 0x84, 0x39, 0x54, 0x20, 0x4f, 0xa0, 0xed, 0x05, 0x27, 0xe1, 0x28, 0x70, 0xad, + 0x78, 0xe4, 0xd3, 0x04, 0x1d, 0xaf, 0xa9, 0x02, 0xa5, 0x91, 0x4f, 0xcd, 0x16, 0x6a, 0xf0, 0x42, + 0x42, 0x36, 0xa1, 0x13, 0x8e, 0x58, 0xd6, 0xa4, 0x3a, 0x6e, 0xd2, 0x56, 0x2a, 0xc2, 0xc6, 0xf8, + 0x25, 0x90, 0xf1, 0x4c, 0x91, 0x3c, 0xc8, 0xf4, 0x64, 0x5e, 0xf5, 0x44, 0x28, 0xe0, 0x58, 0x7d, + 0x04, 0x35, 0x99, 0x2d, 0xe2, 0x50, 0xb5, 0x73, 0x4a, 0x26, 0x56, 0x1a, 0xcf, 0xf2, 0xe8, 0x38, + 0x4e, 0xef, 0x42, 0x37, 0x36, 0xa1, 0xae, 0xca, 0x7c, 0x94, 0x98, 0x47, 0x63, 0x35, 0x4a, 0xfc, + 0xb7, 0x1e, 0xb9, 0x6a, 0x66, 0xe4, 0xfe, 0xa5, 0x02, 0x35, 0x69, 0x44, 0xee, 0x41, 0x43, 0x47, + 0xab, 0x62, 0x2f, 0x6d, 0x98, 0xa9, 0xe0, 0xff, 0x66, 0x5c, 0x39, 0x87, 0x51, 0xc0, 0x62, 0xdb, + 0x79, 0x4b, 0x5d, 0xb1, 0xf8, 0xea, 0x66, 0x2a, 0x20, 0xab, 0x50, 0x8f, 0x62, 0x6a, 0xb9, 0x81, + 0xcd, 0xc4, 0x71, 0x52, 0xe7, 0xbe, 0x45, 0x77, 0x02, 0x9b, 0x19, 0x7f, 0xdf, 0x85, 0x19, 0x0e, + 0x41, 0x96, 0xa1, 0xc6, 0xd3, 0xeb, 0x30, 0xc0, 0xae, 0x63, 0x89, 0x7c, 0x0e, 0xe0, 0x45, 0xd6, + 0x05, 0x8d, 0x13, 0x5e, 0x57, 0x15, 0xeb, 0xba, 0xab, 0xd7, 0xf5, 0x1b, 0x29, 0x37, 0x1b, 0x5e, + 0x84, 0x3f, 0xc9, 0xff, 0xe3, 0x8d, 0x85, 0x2c, 0x74, 0x42, 0x1f, 0xcf, 0xc4, 0xf9, 0xd4, 0x39, + 0x85, 0xd8, 0xd4, 0x0a, 0x64, 0x05, 0xe6, 0x92, 0xd8, 0xb1, 0x02, 0xca, 0x89, 0xf1, 0xd5, 0x57, + 0x4b, 0x62, 0x67, 0x9f, 0x32, 0xf2, 0x19, 0x34, 0x78, 0x45, 0x14, 0xc6, 0x2c, 0xe9, 0xcd, 0x8a, + 0xfe, 0x6b, 0x1f, 0x0f, 0x63, 0x66, 0xda, 0xc1, 0x19, 0x35, 0xeb, 0x49, 0xec, 0xf0, 0x52, 0x42, + 0x9e, 0xc3, 0xaa, 0xc0, 0xb1, 0x87, 0xd4, 0x15, 0x46, 0x96, 0x17, 0x59, 0x09, 0x65, 0x96, 0xe7, + 0x26, 0xbd, 0x96, 0x40, 0x5e, 0xe4, 0xc8, 0xbc, 0x9e, 0x5b, 0x0c, 0xa2, 0x23, 0xca, 0x06, 0x6e, + 0xc2, 0x09, 0xb8, 0x09, 0x13, 0x04, 0x6a, 0x92, 0x80, 0x9b, 0x30, 0x24, 0xc0, 0x2b, 0x24, 0x81, + 0xb9, 0x49, 0x04, 0xdc, 0x84, 0x69, 0x02, 0x02, 0xa7, 0x94, 0x40, 0x5b, 0x12, 0xe0, 0xc8, 0x63, + 0x04, 0xd6, 0xa1, 0xe1, 0x39, 0xc3, 0xc8, 0x12, 0xdb, 0x26, 0x0f, 0x39, 0x66, 0xf7, 0xa6, 0xcc, + 0x3a, 0x17, 0x89, 0x1d, 0xf1, 0x2b, 0xe8, 0xe8, 0x6a, 0xcb, 0x09, 0x5d, 0x75, 0xe6, 0xa8, 0xd4, + 0x69, 0x80, 0x8a, 0x5b, 0x81, 0xbb, 0x1d, 0xba, 0x22, 0x1f, 0x57, 0xb6, 0xbc, 0x4c, 0x1e, 0x41, + 0x87, 0x0f, 0x4c, 0x86, 0x0c, 0x08, 0x32, 0xcd, 0x24, 0x76, 0x34, 0x87, 0x47, 0xd0, 0xe1, 0xe4, + 0x33, 0x4a, 0x4d, 0xa9, 0xe4, 0x26, 0x29, 0xd1, 0x9f, 0xc0, 0x02, 0x2a, 0x89, 0xee, 0x29, 0xcd, + 0x79, 0xa1, 0x39, 0x2f, 0x34, 0x79, 0xc7, 0x50, 0x7b, 0x13, 0x5a, 0x41, 0xc8, 0x2c, 0xed, 0x09, + 0xa7, 0xe5, 0x9e, 0xd0, 0x0c, 0x42, 0xa6, 0x0a, 0xe4, 0x3e, 0xf0, 0xa2, 0xa5, 0x1c, 0xe2, 0x4c, + 0x20, 0x37, 0x82, 0x90, 0x1d, 0x49, 0x9f, 0x78, 0x0a, 0x6d, 0x55, 0x2f, 0xa7, 0xe5, 0x7c, 0xc2, + 0xb4, 0x34, 0xa5, 0x8d, 0x9c, 0x19, 0x44, 0x55, 0xb3, 0xec, 0x69, 0xd4, 0x1d, 0x39, 0xd1, 0x88, + 0x9a, 0x4e, 0xf6, 0x1f, 0xde, 0x80, 0xba, 0xa3, 0xe6, 0xfb, 0x43, 0x69, 0x95, 0x4e, 0xdd, 0x5b, + 0x31, 0x75, 0x15, 0xa1, 0xa5, 0x26, 0x85, 0xec, 0x02, 0xc9, 0x69, 0xc9, 0x19, 0xf4, 0x6f, 0x9c, + 0xc1, 0x8a, 0x39, 0x9f, 0x81, 0x10, 0x93, 0xf8, 0xa9, 0x84, 0x29, 0x4c, 0xe4, 0x50, 0x1e, 0x57, + 0xb2, 0xaf, 0x7a, 0x9a, 0x50, 0xb7, 0x30, 0x9f, 0x81, 0xd6, 0xdd, 0xc9, 0x4c, 0xe9, 0x57, 0xb0, + 0xae, 0x07, 0xbc, 0xd4, 0x71, 0x23, 0x61, 0xb6, 0x82, 0x53, 0x30, 0xe6, 0xbb, 0x68, 0x3f, 0xd9, + 0xf1, 0x7f, 0xd4, 0xf6, 0x3b, 0x65, 0xbe, 0xbf, 0x09, 0x4b, 0x61, 0xec, 0x9d, 0x79, 0x81, 0xed, + 0x0b, 0x12, 0x09, 0xf5, 0xa9, 0xc3, 0xc2, 0xb8, 0x17, 0x8b, 0x2d, 0x68, 0x41, 0x55, 0x1e, 0xc5, + 0xce, 0x11, 0x56, 0xe5, 0x6c, 0x78, 0xc3, 0xda, 0x26, 0xc9, 0xdb, 0xec, 0x24, 0x4c, 0xdb, 0xec, + 0xc2, 0x83, 0x5c, 0x3b, 0xe9, 0x75, 0x84, 0xb6, 0x66, 0xc2, 0xfa, 0x5e, 0xa6, 0x45, 0x7d, 0x29, + 0x51, 0x0a, 0xa3, 0xfa, 0x5c, 0x80, 0x19, 0xe5, 0x61, 0xb0, 0xd7, 0x79, 0x98, 0x17, 0xb0, 0xaa, + 0x61, 0xd4, 0xf0, 0x6b, 0x80, 0x0b, 0x01, 0xb0, 0xac, 0x14, 0xf6, 0xc5, 0xc8, 0x4f, 0x34, 0xcd, + 0x0d, 0xc0, 0xe5, 0x98, 0x69, 0x76, 0x0c, 0xfe, 0x3f, 0x2c, 0x16, 0xc6, 0x5a, 0x64, 0xa4, 0xbd, + 0xdf, 0xc8, 0xed, 0x9e, 0xe4, 0xc6, 0x5a, 0x54, 0x91, 0x1d, 0xb8, 0x5f, 0x66, 0x92, 0xf6, 0xbb, + 0xf7, 0xa7, 0xd2, 0xf8, 0xee, 0xb8, 0xb1, 0xee, 0x76, 0xae, 0x61, 0xc9, 0x57, 0x36, 0xfc, 0xeb, + 0x42, 0xc3, 0x82, 0xec, 0x78, 0xc3, 0x19, 0x93, 0x4c, 0xc3, 0x7f, 0x52, 0x68, 0x38, 0x35, 0x4e, + 0x1b, 0xfe, 0x5e, 0x9e, 0x09, 0xc5, 0x5b, 0xb1, 0xa1, 0xcd, 0x9c, 0xf3, 0xde, 0x55, 0x2e, 0x5b, + 0xcb, 0x5f, 0x8a, 0xbd, 0xe6, 0x1a, 0xe6, 0x72, 0xa2, 0x3b, 0x93, 0x95, 0x73, 0xd8, 0x2c, 0xa7, + 0x3c, 0xec, 0xf5, 0xbb, 0x61, 0x5d, 0x4d, 0x35, 0x07, 0xfb, 0x39, 0xc0, 0x39, 0x63, 0x11, 0xe2, + 0xfc, 0x2a, 0x17, 0xd5, 0xed, 0x1d, 0x1f, 0x1f, 0x4a, 0xeb, 0x06, 0xd7, 0x51, 0x06, 0x75, 0x95, + 0x1f, 0xf7, 0xfe, 0x28, 0x77, 0x41, 0xcb, 0xcf, 0x73, 0x7d, 0xf1, 0xa9, 0x95, 0x78, 0xd4, 0xce, + 0xc3, 0x09, 0xcb, 0x73, 0x7b, 0xbf, 0xc5, 0x33, 0x9e, 0x97, 0x07, 0xee, 0xcb, 0x1a, 0xcc, 0xf0, + 0x2d, 0xea, 0x25, 0x40, 0x5d, 0x6d, 0x57, 0xdf, 0xd6, 0xea, 0xff, 0x5a, 0xe9, 0xfe, 0xb6, 0x62, + 0x82, 0x1f, 0x9e, 0x59, 0x51, 0x4c, 0x4f, 0xbd, 0x2b, 0xe3, 0x1b, 0x58, 0x28, 0xa3, 0xbe, 0x06, + 0x75, 0xed, 0x84, 0x12, 0x58, 0x97, 0x79, 0xba, 0x21, 0x66, 0x0d, 0x63, 0x70, 0x59, 0x30, 0xfe, + 0xae, 0x02, 0x0d, 0xdd, 0x29, 0x99, 0x4e, 0xb0, 0xf3, 0xd0, 0x95, 0xc1, 0x91, 0x48, 0x27, 0x44, + 0x91, 0x3c, 0x81, 0xd9, 0xc8, 0x66, 0xe7, 0x2a, 0x02, 0x5a, 0x2b, 0x8e, 0xc7, 0xe3, 0x43, 0x9b, + 0x9d, 0xcb, 0x91, 0x91, 0x8a, 0x6b, 0xdf, 0x41, 0x43, 0xcb, 0xc8, 0x32, 0xcc, 0xd2, 0x2b, 0xdb, + 0x61, 0x92, 0xd5, 0xde, 0x94, 0x29, 0x8b, 0xa4, 0x07, 0x35, 0xd9, 0x23, 0x19, 0xd2, 0xed, 0x4d, + 0x99, 0x58, 0x7e, 0xd9, 0x02, 0xe0, 0x38, 0x72, 0x16, 0x8c, 0xbf, 0xae, 0x40, 0x2b, 0x3b, 0x98, + 0xe4, 0x6b, 0x68, 0xda, 0x41, 0x10, 0x32, 0x71, 0x89, 0xa4, 0x42, 0xb9, 0x0f, 0x4b, 0x86, 0xfd, + 0xf1, 0x56, 0xaa, 0x26, 0x13, 0xb4, 0xac, 0xe1, 0xda, 0x57, 0xd0, 0x2d, 0x2a, 0xbc, 0x57, 0xaa, + 0xf6, 0x02, 0xe6, 0x0b, 0xc7, 0x86, 0x08, 0x5c, 0xf9, 0x39, 0xc4, 0xed, 0x67, 0x65, 0x6e, 0xc5, + 0x65, 0xe2, 0xc0, 0xa9, 0x4a, 0x19, 0xff, 0x6d, 0xbc, 0x82, 0xba, 0x3e, 0x70, 0x7b, 0x50, 0xc3, + 0xbb, 0x8e, 0x0a, 0x06, 0x1e, 0x58, 0x26, 0x8b, 0xd9, 0x90, 0x77, 0x6f, 0x4a, 0x06, 0xbd, 0x2f, + 0xbb, 0xd0, 0x91, 0xf5, 0x56, 0x18, 0x8b, 0xc5, 0x68, 0x3c, 0x83, 0x86, 0x3e, 0x20, 0x39, 0xdf, + 0x53, 0x2f, 0x4e, 0x18, 0x72, 0x90, 0x05, 0x4e, 0xc2, 0xb7, 0x13, 0xa6, 0x48, 0xf0, 0xdf, 0xc6, + 0x5f, 0x56, 0x80, 0x14, 0x73, 0xf2, 0xc1, 0x0e, 0xcf, 0xc9, 0xc2, 0xd8, 0x39, 0xa7, 0x09, 0x8b, + 0x6d, 0x16, 0xc6, 0xdc, 0x53, 0x65, 0xd7, 0x3b, 0x59, 0xf1, 0xc0, 0x25, 0x0f, 0xa0, 0xa9, 0x2f, + 0x00, 0x3c, 0x19, 0xf0, 0x36, 0x4c, 0x50, 0x22, 0xa9, 0xa0, 0x2f, 0x06, 0x3c, 0x57, 0x04, 0xbd, + 0x0d, 0x13, 0x94, 0x68, 0xe0, 0x7e, 0x3b, 0x53, 0xaf, 0x74, 0xab, 0x66, 0xfd, 0x3c, 0x4c, 0x98, + 0xe8, 0xc8, 0x15, 0x2c, 0x97, 0x7f, 0x82, 0x21, 0x9f, 0x64, 0xd2, 0x87, 0xd5, 0x09, 0xf7, 0x09, + 0x98, 0xa6, 0x7c, 0x01, 0x75, 0xd5, 0x04, 0x5e, 0xaa, 0xac, 0x4c, 0xfa, 0x06, 0xa3, 0x15, 0x8d, + 0xff, 0x98, 0x86, 0x6e, 0xb1, 0x9a, 0x0f, 0x65, 0xc2, 0x6c, 0xa6, 0xb2, 0x35, 0x59, 0x28, 0x4b, + 0x44, 0xb8, 0xdb, 0x0c, 0x6d, 0x07, 0x87, 0x80, 0xff, 0xe4, 0x7d, 0x57, 0xdf, 0xfe, 0xf8, 0x19, + 0x2c, 0xe3, 0x6a, 0x40, 0x11, 0x3f, 0x76, 0xef, 0x42, 0xc3, 0x8b, 0x2e, 0x9e, 0xf2, 0x70, 0x48, + 0xc6, 0xd6, 0x0d, 0xb3, 0xce, 0x05, 0xfb, 0x94, 0xa9, 0xca, 0xbe, 0xac, 0xac, 0xe9, 0xca, 0xbe, + 0xa8, 0xfc, 0x08, 0x66, 0x79, 0x46, 0xa4, 0x02, 0x62, 0x15, 0xce, 0x1d, 0x7b, 0x34, 0x1e, 0x04, + 0xa7, 0xa1, 0x29, 0x6b, 0xc9, 0x27, 0x50, 0x97, 0x0d, 0xd8, 0xac, 0x57, 0x17, 0x9a, 0x1d, 0x7d, + 0xd3, 0xcf, 0x84, 0xe2, 0x9c, 0x68, 0xcf, 0x66, 0xa8, 0xda, 0x17, 0xaa, 0x8d, 0x89, 0xaa, 0x7d, + 0xae, 0xba, 0x05, 0xeb, 0xb6, 0xef, 0x87, 0x97, 0x56, 0x12, 0x85, 0xe1, 0x29, 0x75, 0xad, 0x24, + 0x1c, 0xc5, 0x0e, 0xc5, 0xcd, 0x89, 0xaa, 0xc8, 0x76, 0x4d, 0x28, 0x1d, 0x49, 0x9d, 0x23, 0xa1, + 0x72, 0x88, 0x1a, 0xe4, 0xdb, 0xfc, 0xfa, 0x6d, 0x8a, 0x06, 0x37, 0x26, 0xcc, 0xd1, 0xff, 0xf2, + 0x1a, 0xde, 0x1e, 0xf7, 0x38, 0x4c, 0x58, 0x6f, 0xef, 0x71, 0xc6, 0x16, 0x74, 0xb2, 0xf7, 0x75, + 0x83, 0x9d, 0xa2, 0xe7, 0x57, 0xdf, 0xe9, 0xf9, 0x3e, 0x90, 0xf1, 0xcf, 0xa3, 0xe4, 0xa3, 0x0c, + 0x87, 0xa5, 0x92, 0x9b, 0x41, 0xf4, 0xf8, 0xcf, 0x33, 0x1e, 0x3f, 0x9d, 0x3b, 0x84, 0x72, 0xdf, + 0x48, 0x53, 0x6f, 0xff, 0xf7, 0x2a, 0xb4, 0xb2, 0x55, 0x65, 0xd7, 0x12, 0x45, 0x0f, 0xae, 0x8e, + 0x79, 0xb0, 0xf6, 0xc3, 0xe9, 0x1b, 0xfd, 0xf0, 0xa7, 0x30, 0xaf, 0x93, 0x60, 0x4b, 0x1a, 0xd4, + 0xca, 0x0d, 0x3a, 0x5a, 0xef, 0x58, 0x58, 0x3e, 0x83, 0x8e, 0xca, 0x98, 0xad, 0x1b, 0x3d, 0xbe, + 0x85, 0x89, 0xb4, 0x34, 0x7b, 0x0a, 0xed, 0xd3, 0x30, 0xbe, 0xb4, 0x63, 0xd5, 0x5c, 0x7d, 0x82, + 0x15, 0x6a, 0x49, 0xab, 0xc7, 0xb0, 0x40, 0xaf, 0x22, 0xea, 0x30, 0xea, 0x5a, 0x62, 0xdd, 0xd8, + 0xae, 0x1b, 0xab, 0x85, 0x7b, 0x47, 0x55, 0x0d, 0xa2, 0x8b, 0xa7, 0x5b, 0xbc, 0xa2, 0xa8, 0xdf, + 0x47, 0xfd, 0xd9, 0x31, 0xfd, 0xbe, 0xd0, 0x37, 0x7e, 0x27, 0x3f, 0xc3, 0xe8, 0x65, 0xb7, 0x9b, + 0x61, 0x23, 0x86, 0xba, 0xa2, 0x5d, 0x3a, 0x57, 0x9f, 0x40, 0xd7, 0x0b, 0xce, 0x62, 0x9a, 0x24, + 0xf2, 0x83, 0xbe, 0xa7, 0xcf, 0xfa, 0x79, 0x94, 0x1f, 0xa2, 0x98, 0x6f, 0xef, 0xb4, 0xa0, 0x89, + 0x57, 0x6e, 0x34, 0xa7, 0x68, 0x3c, 0x87, 0x39, 0x5c, 0xfd, 0x64, 0x09, 0x6a, 0xf4, 0x8a, 0xe7, + 0x14, 0x6a, 0x27, 0xa4, 0x57, 0x6c, 0x10, 0x71, 0xb1, 0x70, 0xf0, 0x48, 0xad, 0x2b, 0x4e, 0x38, + 0x32, 0x4c, 0x58, 0x28, 0xb9, 0x78, 0x27, 0x8f, 0xa0, 0xed, 0x25, 0xa1, 0xc5, 0xbc, 0x21, 0x4d, + 0x98, 0x3d, 0x54, 0x58, 0x2d, 0x2f, 0x09, 0x8f, 0x95, 0x8c, 0x2c, 0x43, 0x6d, 0x14, 0x71, 0x15, + 0x01, 0x59, 0x31, 0xb1, 0x64, 0x44, 0xd0, 0x9b, 0x74, 0xe9, 0x7e, 0xdb, 0x55, 0xf2, 0x19, 0xd4, + 0xe4, 0xbd, 0x31, 0x5e, 0x5f, 0x2d, 0xe9, 0x8f, 0x54, 0xb9, 0xeb, 0x66, 0x54, 0x32, 0x36, 0xa0, + 0x93, 0xaf, 0xe1, 0xdc, 0x10, 0x00, 0x03, 0x37, 0xd4, 0xdc, 0x2a, 0xe3, 0xf6, 0x7e, 0xf3, 0x7b, + 0x05, 0xf7, 0x6e, 0xba, 0x8b, 0x7f, 0x9f, 0xe3, 0xef, 0x3d, 0xbb, 0x39, 0x98, 0xd4, 0xf2, 0xfb, + 0x6f, 0x83, 0x67, 0xb0, 0x54, 0x7a, 0xf9, 0x4e, 0xd6, 0x01, 0xa2, 0xd1, 0x89, 0xef, 0x39, 0x56, + 0xba, 0x2f, 0x37, 0xa4, 0xe4, 0x3b, 0x7a, 0xfd, 0xde, 0x97, 0x5b, 0xc6, 0x6b, 0xb9, 0x94, 0x0a, + 0xaf, 0x14, 0xd6, 0x40, 0x6f, 0xa7, 0x2a, 0x00, 0x56, 0x65, 0x7d, 0xd8, 0xf2, 0x35, 0x8a, 0xce, + 0x2a, 0x0e, 0x47, 0xbe, 0x34, 0x8b, 0x70, 0xd8, 0xf1, 0xff, 0x32, 0xdc, 0x01, 0x2c, 0x96, 0x7d, + 0x67, 0xbb, 0x05, 0x60, 0xbf, 0x08, 0xd8, 0x2f, 0x07, 0xbc, 0x35, 0xc3, 0x09, 0x80, 0xbb, 0xd0, + 0xc9, 0xbf, 0xb0, 0x28, 0xb9, 0xbc, 0x9f, 0x89, 0xc2, 0xd0, 0x47, 0x17, 0x9a, 0x2f, 0xbe, 0xa9, 0x10, 0x95, 0xc6, 0xc3, 0x14, 0x66, 0xc2, 0xb5, 0xfc, 0xaf, 0xa0, 0xae, 0x34, 0x44, 0x18, 0xec, 0xb9, 0xfa, 0x4e, 0x97, 0xff, 0x26, 0xf7, 0x01, 0x86, 0x76, 0xf2, 0xe3, 0x88, 0xc6, 0x36, 0x06, 0xc8, 0x75, 0x33, 0x23, 0x91, 0xbd, 0xf0, 0x22, 0x6b, 0xc8, 0xe3, 0xe7, 0x69, 0xd5, 0x0b, 0x2f, 0x7a, 0xcd, 0x63, 0xed, 0x75, 0x80, 0x8b, 0x2b, 0xdf, 0x0e, 0x64, 0xad, 0x0c, 0x2e, 0x1b, 0x42, - 0xc2, 0xab, 0x8d, 0x3f, 0xad, 0x40, 0x3b, 0xf7, 0xfd, 0x99, 0x7c, 0x00, 0x2d, 0x81, 0x46, 0x03, + 0xc2, 0xab, 0x8d, 0x3f, 0xae, 0x40, 0x3b, 0xf7, 0xfd, 0x99, 0x7c, 0x00, 0x2d, 0x81, 0x46, 0x03, 0xfb, 0xc4, 0xa7, 0x92, 0x67, 0xdd, 0x6c, 0x72, 0xd9, 0xae, 0x14, 0xf1, 0x3d, 0x4a, 0x62, 0x2a, 0x1d, 0xc9, 0xa9, 0x25, 0x84, 0x4a, 0x69, 0x03, 0xba, 0x39, 0x25, 0xeb, 0xa2, 0x8f, 0xb7, 0xbd, - 0x9d, 0xac, 0xde, 0x9b, 0xbe, 0xf1, 0x4f, 0x15, 0x58, 0x2c, 0x7b, 0x3f, 0x42, 0x3e, 0xce, 0xac, + 0x9d, 0xac, 0xde, 0x9b, 0xbe, 0xf1, 0x8f, 0x15, 0x58, 0x2c, 0x7b, 0x3f, 0x42, 0x3e, 0xce, 0xac, 0xaa, 0x95, 0xd2, 0x3c, 0x15, 0x57, 0xf3, 0xcf, 0xa1, 0xe6, 0xdb, 0x27, 0xd4, 0x57, 0xc9, 0xd7, 0xc7, 0x37, 0xbc, 0x4a, 0x79, 0xfc, 0x4a, 0x68, 0xe2, 0xa7, 0x28, 0x69, 0xb6, 0xf6, 0x02, 0x9a, - 0x19, 0xf1, 0x7b, 0xc5, 0x46, 0x3f, 0x2f, 0x92, 0xc7, 0x51, 0xbe, 0x2d, 0x79, 0x63, 0x07, 0xba, - 0x45, 0x79, 0xfe, 0x9e, 0xbe, 0x52, 0xbc, 0xa7, 0x2f, 0xbb, 0xe4, 0xff, 0xc7, 0x0a, 0xcc, 0x17, - 0x1e, 0xb8, 0x10, 0x23, 0x43, 0x81, 0x14, 0xdf, 0xaf, 0xa0, 0xeb, 0xbe, 0x2c, 0xb8, 0xce, 0x28, - 0x7f, 0x2c, 0xf3, 0xbf, 0xed, 0xb5, 0x67, 0x19, 0xb6, 0xe8, 0xb0, 0x5b, 0xb0, 0x35, 0x3e, 0x80, - 0x66, 0x46, 0x54, 0xfa, 0x9d, 0xe8, 0x18, 0x40, 0xbe, 0x53, 0x39, 0xc6, 0xb4, 0x92, 0xcf, 0x5c, - 0x9c, 0xc5, 0xe2, 0xb7, 0x60, 0xc5, 0x67, 0x20, 0x4e, 0x5b, 0x59, 0xe0, 0x2e, 0xd7, 0xdf, 0x3e, - 0xd5, 0x67, 0x09, 0x2d, 0x30, 0xfe, 0xbd, 0x0a, 0xcd, 0xcc, 0xcb, 0x1d, 0xf2, 0x61, 0x26, 0x85, - 0x4d, 0xf7, 0x61, 0xa1, 0x91, 0x7e, 0x30, 0x24, 0x5f, 0xf0, 0xb5, 0x24, 0x9f, 0x5f, 0x09, 0x6d, - 0xb9, 0x6b, 0xdf, 0xd1, 0x1b, 0x05, 0x5f, 0xf2, 0x42, 0x1d, 0xbc, 0x48, 0xfd, 0xe6, 0x6e, 0x74, - 0x13, 0xa6, 0xb2, 0x24, 0x37, 0x61, 0xc4, 0x80, 0xb6, 0xb8, 0xc3, 0x0b, 0x5d, 0x79, 0xaf, 0x84, - 0xcb, 0xb8, 0xe9, 0x26, 0x6c, 0x3f, 0x74, 0xc5, 0x35, 0x12, 0xb9, 0x0f, 0x4d, 0xad, 0xe3, 0x45, - 0xea, 0xdb, 0x0e, 0x6a, 0x0c, 0x22, 0x1e, 0xa7, 0x26, 0xf6, 0x90, 0x5a, 0xc9, 0xe8, 0x24, 0xa0, - 0x4c, 0x7c, 0x73, 0xae, 0x9b, 0xc0, 0x45, 0x47, 0x42, 0xc2, 0xd7, 0x3d, 0x8f, 0x20, 0xc3, 0x11, - 0x3b, 0x0b, 0xbd, 0xe0, 0x4c, 0xdc, 0xef, 0xd7, 0xcd, 0x66, 0x60, 0xb3, 0x03, 0x14, 0x91, 0x8f, - 0xa0, 0xe3, 0x87, 0x8e, 0xed, 0x5b, 0x2a, 0x7b, 0x15, 0x17, 0xfc, 0x75, 0xb3, 0x2d, 0xa4, 0xea, - 0xbc, 0x23, 0x9b, 0xd0, 0x64, 0x62, 0x04, 0x64, 0xa7, 0xe5, 0x7b, 0x44, 0xd5, 0xe9, 0x74, 0x6c, - 0x4c, 0x60, 0xfa, 0xb7, 0xf1, 0x00, 0xdd, 0x8b, 0x73, 0x01, 0x7d, 0x50, 0xd5, 0x3e, 0x30, 0xfe, - 0xa3, 0x02, 0xab, 0x13, 0x5f, 0x32, 0x89, 0x89, 0xc0, 0xf7, 0x37, 0x35, 0x11, 0xf8, 0xce, 0x87, - 0xd9, 0x66, 0x35, 0xcd, 0x36, 0x73, 0x07, 0xd2, 0x74, 0xfe, 0x40, 0xe2, 0xfb, 0x55, 0x64, 0xc7, - 0x34, 0x60, 0x96, 0x4b, 0xc5, 0x6d, 0x99, 0x17, 0xa1, 0x9f, 0x3b, 0x52, 0xbe, 0x23, 0xc4, 0x32, - 0xa0, 0x1b, 0xda, 0x0e, 0xdf, 0xcf, 0xa4, 0x97, 0x67, 0x87, 0xb6, 0xf3, 0xa6, 0x9f, 0x3f, 0x4c, - 0x6a, 0xf9, 0xc3, 0x84, 0xfc, 0x04, 0x48, 0x11, 0xfd, 0xa2, 0x2f, 0x46, 0xa1, 0x61, 0x76, 0xf3, - 0xf8, 0x17, 0x7d, 0xe3, 0xf3, 0xd2, 0xbe, 0xa2, 0x6f, 0x4a, 0xfa, 0x6a, 0xfc, 0xa6, 0x02, 0x2b, - 0x13, 0xde, 0x53, 0xdd, 0x78, 0x00, 0xe6, 0x63, 0x8e, 0x6a, 0x31, 0xe6, 0x78, 0x0c, 0x0b, 0x5e, - 0xc0, 0x68, 0x7c, 0x6a, 0x4b, 0xc6, 0x39, 0xd7, 0xdd, 0xd1, 0x55, 0x2a, 0xdc, 0x37, 0x9e, 0x95, - 0xb0, 0x78, 0xf7, 0x31, 0x6c, 0xfc, 0x65, 0x05, 0x56, 0x27, 0xbe, 0x1c, 0xba, 0x91, 0xbf, 0x01, - 0xed, 0x94, 0x3f, 0x1f, 0x11, 0xd9, 0x85, 0xa6, 0xee, 0xc2, 0x9b, 0xfe, 0x58, 0x27, 0xfa, 0x13, - 0x3b, 0x21, 0xcf, 0xfd, 0xe7, 0xa5, 0x64, 0x6e, 0xd1, 0x8d, 0x7f, 0xae, 0xc0, 0x52, 0xe9, 0xcb, - 0x30, 0xb2, 0x09, 0x4b, 0xea, 0x0e, 0xd6, 0xf1, 0x47, 0x09, 0xa3, 0xb1, 0xc5, 0x4f, 0x76, 0x75, - 0x87, 0xb8, 0x80, 0x95, 0xdb, 0xb2, 0x6e, 0x9b, 0x57, 0x91, 0xa7, 0xe9, 0x23, 0x49, 0x7a, 0xc5, - 0x68, 0x1c, 0xd8, 0x3e, 0x1a, 0x55, 0xf1, 0x1b, 0xa1, 0xac, 0xdd, 0xc5, 0x4a, 0x69, 0xf5, 0x33, - 0x58, 0x53, 0x56, 0x7c, 0x2d, 0x9e, 0xd8, 0xbe, 0x1d, 0x38, 0xba, 0x39, 0x99, 0xc2, 0xf4, 0x50, - 0xe3, 0x55, 0x46, 0x41, 0x58, 0x1b, 0xff, 0x52, 0x81, 0x76, 0xee, 0x39, 0x59, 0x69, 0x1a, 0x95, - 0x3b, 0x9c, 0xaa, 0x25, 0x87, 0x93, 0x7e, 0x56, 0xd1, 0xc0, 0x7d, 0x70, 0x1d, 0x40, 0xf5, 0x5b, - 0xaf, 0xaa, 0x06, 0x4a, 0x06, 0x11, 0x4f, 0xb6, 0x72, 0x64, 0xf5, 0xfe, 0xd5, 0xc9, 0x8a, 0x07, - 0x11, 0xdf, 0xa3, 0xb4, 0x2f, 0xbc, 0x48, 0xdd, 0xf9, 0x34, 0x95, 0x6c, 0x10, 0xf1, 0x34, 0xa3, - 0x9d, 0x7b, 0xd1, 0xf6, 0xfe, 0x3d, 0xf8, 0x74, 0x03, 0x1a, 0x3a, 0xa0, 0x26, 0x73, 0x30, 0xbd, - 0xb5, 0xff, 0x8b, 0xee, 0x14, 0xa9, 0xc3, 0xcc, 0xe0, 0xf0, 0xcd, 0xd3, 0xee, 0x0c, 0xfe, 0xea, - 0x77, 0x6b, 0x9f, 0xfe, 0x45, 0x05, 0x1a, 0x7a, 0xcf, 0x27, 0x6d, 0x68, 0x6c, 0x0f, 0x76, 0x4c, - 0x6b, 0xb0, 0xff, 0xf5, 0x41, 0x77, 0x8a, 0x2c, 0xc0, 0xbc, 0xb9, 0xfb, 0xfa, 0xe0, 0x78, 0xd7, - 0xfa, 0xe1, 0xc0, 0xfc, 0xee, 0xd5, 0xc1, 0xd6, 0x4e, 0xb7, 0x42, 0xe6, 0xa1, 0x89, 0xc2, 0xbd, - 0x83, 0xa3, 0xe3, 0x6e, 0x95, 0x10, 0xe8, 0xbc, 0x3a, 0xd8, 0xde, 0x7a, 0x95, 0x2a, 0x4d, 0x93, - 0x0e, 0x80, 0x94, 0x09, 0x9d, 0x19, 0x72, 0x07, 0xda, 0x68, 0x74, 0xfc, 0xfd, 0xfe, 0xfe, 0xee, - 0xab, 0xee, 0x2c, 0xe9, 0x42, 0x4b, 0xaa, 0xa0, 0xa4, 0xf6, 0xe9, 0x0b, 0x80, 0xf4, 0x40, 0xe1, - 0x1c, 0xf7, 0x0f, 0xf6, 0x77, 0xbb, 0x53, 0xa4, 0x05, 0xf5, 0xfd, 0x03, 0x6b, 0x77, 0x7f, 0x7b, - 0xeb, 0xb0, 0x5b, 0x21, 0x0d, 0x98, 0x15, 0x3b, 0x4b, 0xb7, 0x2a, 0xbb, 0x31, 0x38, 0xec, 0x4e, - 0x6f, 0x7e, 0x05, 0x20, 0xdf, 0x07, 0x88, 0xff, 0x51, 0x78, 0x02, 0x33, 0xe2, 0xaf, 0x3a, 0x83, - 0x33, 0xff, 0x22, 0xb1, 0xa6, 0x64, 0x99, 0x7f, 0x93, 0x78, 0x52, 0x79, 0x39, 0xf7, 0x87, 0xb3, - 0xe2, 0xe3, 0xe9, 0x49, 0x4d, 0xfc, 0xf9, 0xe2, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x14, 0x49, - 0xe8, 0x11, 0x74, 0x31, 0x00, 0x00, + 0x19, 0xf1, 0x7b, 0xc5, 0x46, 0x3f, 0x2f, 0x92, 0xc7, 0x59, 0xbe, 0x2d, 0x79, 0x63, 0x07, 0xba, + 0x45, 0x79, 0xfe, 0x9e, 0xbe, 0x52, 0xbc, 0xa7, 0x2f, 0xbb, 0xe4, 0xff, 0x87, 0x0a, 0xcc, 0x17, + 0x1e, 0xb8, 0x10, 0x23, 0x43, 0x81, 0x14, 0xdf, 0xaf, 0xe0, 0xd0, 0x7d, 0x59, 0x18, 0x3a, 0xa3, + 0xfc, 0xb1, 0xcc, 0xff, 0xf4, 0xa8, 0x3d, 0xcb, 0xb0, 0xc5, 0x01, 0xbb, 0x05, 0x5b, 0xe3, 0x03, + 0x68, 0x66, 0x44, 0xa5, 0xdf, 0x89, 0x8e, 0x01, 0xe4, 0x3b, 0x95, 0x63, 0x4c, 0x2b, 0xb9, 0xe7, + 0xa2, 0x17, 0x8b, 0xdf, 0x82, 0x15, 0xf7, 0x40, 0x74, 0x5b, 0x59, 0xe0, 0x43, 0xae, 0xbf, 0x7d, + 0xaa, 0xcf, 0x12, 0x5a, 0x60, 0xfc, 0xed, 0x0c, 0x34, 0x33, 0x2f, 0x77, 0xc8, 0x87, 0x99, 0x14, + 0x36, 0xdd, 0x87, 0x85, 0x46, 0xfa, 0xc1, 0x90, 0x7c, 0xc1, 0xd7, 0x92, 0x7c, 0x7e, 0x25, 0xb4, + 0xe5, 0xae, 0x7d, 0x47, 0x6f, 0x14, 0x7c, 0xc9, 0x0b, 0x75, 0xf0, 0x22, 0xf5, 0x9b, 0x0f, 0xa3, + 0x9b, 0x30, 0x95, 0x25, 0xb9, 0x09, 0x23, 0x06, 0xb4, 0xc5, 0x1d, 0x5e, 0xe8, 0xca, 0x7b, 0x25, + 0x5c, 0xc6, 0x4d, 0x37, 0x61, 0xfb, 0xa1, 0x2b, 0xae, 0x91, 0xc8, 0x7d, 0x68, 0x6a, 0x1d, 0x2f, + 0x52, 0xdf, 0x76, 0x50, 0x63, 0x10, 0xf1, 0x38, 0x35, 0xb1, 0x87, 0xd4, 0x4a, 0x46, 0x27, 0x01, + 0x65, 0xe2, 0x9b, 0x73, 0xdd, 0x04, 0x2e, 0x3a, 0x12, 0x12, 0xbe, 0xee, 0x79, 0x04, 0x19, 0x8e, + 0xd8, 0x59, 0xe8, 0x05, 0x67, 0xe2, 0x7e, 0xbf, 0x6e, 0x36, 0x03, 0x9b, 0x1d, 0xa0, 0x88, 0x7c, + 0x04, 0x1d, 0x3f, 0x74, 0x6c, 0xdf, 0x52, 0xd9, 0xab, 0xb8, 0xe0, 0xaf, 0x9b, 0x6d, 0x21, 0x55, + 0xe7, 0x1d, 0xd9, 0x84, 0x26, 0x13, 0x33, 0x20, 0x3b, 0x2d, 0xdf, 0x23, 0xaa, 0x4e, 0xa7, 0x73, + 0x63, 0x02, 0x4b, 0xe7, 0xa9, 0xaf, 0xdd, 0x50, 0x26, 0x3a, 0xf7, 0xc7, 0x5f, 0x4b, 0x95, 0xb9, + 0x20, 0xdf, 0xdd, 0xed, 0x04, 0x2f, 0x06, 0x5a, 0x72, 0xeb, 0x53, 0x65, 0xf2, 0x04, 0x16, 0xd3, + 0x8f, 0xe1, 0x99, 0xa3, 0xb5, 0x2d, 0x2f, 0xf3, 0x74, 0xdd, 0xa1, 0x3a, 0x63, 0xff, 0x3b, 0x0e, + 0xfd, 0x00, 0xfd, 0x03, 0x9d, 0x19, 0x27, 0xb1, 0xaa, 0x27, 0xd1, 0xf8, 0xb7, 0x0a, 0xac, 0x4e, + 0x7c, 0x8a, 0x25, 0x3c, 0x99, 0x6f, 0xd0, 0xca, 0x93, 0xf9, 0xd6, 0x8d, 0xe9, 0x72, 0x35, 0x4d, + 0x97, 0x73, 0x27, 0xea, 0x74, 0xfe, 0x44, 0xe5, 0x1b, 0x6e, 0x64, 0xc7, 0x34, 0x60, 0x96, 0x4b, + 0xc5, 0x75, 0x9f, 0x17, 0xa1, 0xa3, 0x74, 0xa4, 0x7c, 0x47, 0x88, 0x65, 0x44, 0x3a, 0xb4, 0x1d, + 0xbe, 0x21, 0x4b, 0x37, 0x99, 0x1d, 0xda, 0xce, 0x9b, 0x7e, 0xfe, 0x34, 0xac, 0xe5, 0x4f, 0x43, + 0xf2, 0x13, 0x20, 0x45, 0xf4, 0x8b, 0xbe, 0x70, 0xa3, 0x86, 0xd9, 0xcd, 0xe3, 0x5f, 0xf4, 0x8d, + 0xcf, 0x4b, 0xfb, 0x8a, 0x63, 0x53, 0xd2, 0x57, 0xe3, 0x37, 0x15, 0x58, 0x99, 0xf0, 0x20, 0xec, + 0xc6, 0x13, 0x3c, 0x1f, 0x34, 0x55, 0x8b, 0x41, 0xd3, 0x63, 0x58, 0xf0, 0x02, 0x46, 0xe3, 0x53, + 0x5b, 0x32, 0xce, 0x0d, 0xdd, 0x1d, 0x5d, 0xa5, 0xf2, 0x15, 0xe3, 0x59, 0x09, 0x8b, 0x77, 0xc7, + 0x11, 0xc6, 0x9f, 0x57, 0x60, 0x75, 0xe2, 0xd3, 0xa7, 0x1b, 0xf9, 0x1b, 0xd0, 0x4e, 0xf9, 0xf3, + 0x19, 0x91, 0x5d, 0x68, 0xea, 0x2e, 0xbc, 0xe9, 0x8f, 0x75, 0xa2, 0x3f, 0xb1, 0x13, 0x32, 0x70, + 0x79, 0x5e, 0x4a, 0xe6, 0x16, 0xdd, 0xf8, 0xa7, 0x0a, 0x2c, 0x95, 0x3e, 0x6d, 0x23, 0x9b, 0xb0, + 0xa4, 0x2e, 0x91, 0x1d, 0x7f, 0x94, 0x30, 0x1a, 0x5b, 0x3c, 0x34, 0x51, 0x97, 0xa0, 0x0b, 0x58, + 0xb9, 0x2d, 0xeb, 0xb6, 0x79, 0x15, 0x79, 0x9a, 0xbe, 0xf2, 0xa4, 0x57, 0x8c, 0xc6, 0x81, 0xed, + 0xa3, 0x51, 0x15, 0x3f, 0x72, 0xca, 0xda, 0x5d, 0xac, 0x94, 0x56, 0x3f, 0x83, 0x35, 0x65, 0xc5, + 0x37, 0x93, 0x13, 0xdb, 0xb7, 0x03, 0x47, 0x37, 0x27, 0x73, 0xb0, 0x1e, 0x6a, 0xbc, 0xca, 0x28, + 0x08, 0x6b, 0xe3, 0x9f, 0x2b, 0xd0, 0xce, 0xbd, 0x87, 0x2b, 0xcd, 0x03, 0x73, 0xa7, 0x6b, 0xb5, + 0xe4, 0x74, 0xd5, 0xef, 0x42, 0x1a, 0xb8, 0x91, 0xaf, 0x03, 0xa8, 0x7e, 0xeb, 0x55, 0xd5, 0x40, + 0xc9, 0x20, 0xe2, 0xd9, 0x62, 0x8e, 0xac, 0xde, 0x80, 0x3b, 0x59, 0xf1, 0x20, 0xe2, 0x9b, 0xac, + 0x1e, 0x0b, 0x2f, 0x52, 0x97, 0x56, 0x4d, 0x25, 0x1b, 0x44, 0x3c, 0x4f, 0x6a, 0xe7, 0x9e, 0xe4, + 0xbd, 0x7f, 0x0f, 0x3e, 0xdd, 0x80, 0x86, 0xce, 0x08, 0xc8, 0x1c, 0x4c, 0x6f, 0xed, 0xff, 0xa2, + 0x3b, 0x45, 0xea, 0x30, 0x33, 0x38, 0x7c, 0xf3, 0xb4, 0x3b, 0x83, 0xbf, 0xfa, 0xdd, 0xda, 0xa7, + 0x7f, 0x56, 0x81, 0x86, 0x3e, 0xb4, 0x48, 0x1b, 0x1a, 0xdb, 0x83, 0x1d, 0xd3, 0x1a, 0xec, 0x7f, + 0x7d, 0xd0, 0x9d, 0x22, 0x0b, 0x30, 0x6f, 0xee, 0xbe, 0x3e, 0x38, 0xde, 0xb5, 0x7e, 0x38, 0x30, + 0xbf, 0x7b, 0x75, 0xb0, 0xb5, 0xd3, 0xad, 0x90, 0x79, 0x68, 0xa2, 0x70, 0xef, 0xe0, 0xe8, 0xb8, + 0x5b, 0x25, 0x04, 0x3a, 0xaf, 0x0e, 0xb6, 0xb7, 0x5e, 0xa5, 0x4a, 0xd3, 0xa4, 0x03, 0x20, 0x65, + 0x42, 0x67, 0x86, 0xdc, 0x81, 0x36, 0x1a, 0x1d, 0x7f, 0xbf, 0xbf, 0xbf, 0xfb, 0xaa, 0x3b, 0x4b, + 0xba, 0xd0, 0x92, 0x2a, 0x28, 0xa9, 0x7d, 0xfa, 0x02, 0x20, 0x3d, 0x11, 0x39, 0xc7, 0xfd, 0x83, + 0xfd, 0xdd, 0xee, 0x14, 0x69, 0x41, 0x7d, 0xff, 0xc0, 0xda, 0xdd, 0xdf, 0xde, 0x3a, 0xec, 0x56, + 0x48, 0x03, 0x66, 0xc5, 0xce, 0xd2, 0xad, 0xca, 0x6e, 0x0c, 0x0e, 0xbb, 0xd3, 0x9b, 0x5f, 0x01, + 0xc8, 0x07, 0x0e, 0xe2, 0x9f, 0x2c, 0x9e, 0xc0, 0x8c, 0xf8, 0xab, 0x82, 0x88, 0xcc, 0xff, 0x78, + 0xac, 0x29, 0x59, 0xe6, 0xff, 0x3c, 0x9e, 0x54, 0x5e, 0xce, 0xfd, 0xfe, 0xac, 0xf8, 0xfa, 0x7b, + 0x52, 0x13, 0x7f, 0xbe, 0xf8, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x1d, 0x28, 0x03, 0x35, + 0x32, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/calico-vpp-agent/proto/felixbackend.proto b/calico-vpp-agent/proto/felixbackend.proto index cfdfac356..d166d91bb 100644 --- a/calico-vpp-agent/proto/felixbackend.proto +++ b/calico-vpp-agent/proto/felixbackend.proto @@ -568,6 +568,9 @@ message RouteUpdate { bool nat_outgoing = 8; bool local_workload = 9; TunnelType tunnel_type = 10; + map labels = 11; + string asnumber = 12; + string wireguard_public_key = 13; } message RouteRemove { diff --git a/calico-vpp-agent/routing/routing_server.go b/calico-vpp-agent/routing/routing_server.go index 7c7e1eada..c1b462309 100644 --- a/calico-vpp-agent/routing/routing_server.go +++ b/calico-vpp-agent/routing/routing_server.go @@ -24,7 +24,6 @@ import ( bgpserver "github.com/osrg/gobgp/pkg/server" "github.com/pkg/errors" calicov3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" "golang.org/x/net/context" @@ -55,7 +54,7 @@ type Server struct { routingServerEventChan chan common.CalicoVppEvent - nodeBGPSpec *oldv3.NodeBGPSpec + nodeBGPSpec *common.LocalNodeSpec } func (s *Server) SetBGPConf(bgpConf *calicov3.BGPConfigurationSpec) { @@ -69,7 +68,7 @@ func (s *Server) SetBGPConf(bgpConf *calicov3.BGPConfigurationSpec) { } } -func (s *Server) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (s *Server) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { s.nodeBGPSpec = nodeBGPSpec } @@ -178,6 +177,7 @@ func (s *Server) getGoBGPGlobalConfig() (*bgpapi.Global, error) { asn := s.nodeBGPSpec.ASNumber if asn == nil { asn = s.BGPConf.ASNumber + s.log.Infof("herere %+v", asn) } nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(s.nodeBGPSpec) diff --git a/calico-vpp-agent/services/service_server.go b/calico-vpp-agent/services/service_server.go index f94de6e8c..29cb325ae 100644 --- a/calico-vpp-agent/services/service_server.go +++ b/calico-vpp-agent/services/service_server.go @@ -21,7 +21,6 @@ import ( "time" calicov3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/sirupsen/logrus" tomb "gopkg.in/tomb.v2" v1 "k8s.io/api/core/v1" @@ -67,7 +66,7 @@ type Server struct { lock sync.Mutex /* protects handleServiceEndpointEvent(s)/Serve */ BGPConf *calicov3.BGPConfigurationSpec - nodeBGPSpec *oldv3.NodeBGPSpec + nodeBGPSpec *common.LocalNodeSpec serviceStateMap map[string]ServiceState @@ -78,7 +77,7 @@ func (s *Server) SetBGPConf(bgpConf *calicov3.BGPConfigurationSpec) { s.BGPConf = bgpConf } -func (s *Server) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (s *Server) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { s.nodeBGPSpec = nodeBGPSpec } diff --git a/calico-vpp-agent/watchers/kernel_watcher.go b/calico-vpp-agent/watchers/kernel_watcher.go new file mode 100644 index 000000000..d32105972 --- /dev/null +++ b/calico-vpp-agent/watchers/kernel_watcher.go @@ -0,0 +1,138 @@ +// Copyright (C) 2020 Cisco Systems Inc. +// +// 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 watchers + +import ( + "net" + "syscall" + + "github.com/sirupsen/logrus" + "github.com/vishvananda/netlink" + tomb "gopkg.in/tomb.v2" + + "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" +) + +type KernelWatcher struct { + log *logrus.Entry + ipam IpamCache + nodeBGPSpec *common.LocalNodeSpec +} + +// watchKernelRoute receives netlink route update notification and announces +// kernel/boot routes using BGP. +// TODO: should we leverage this to update VPP routes as well? +func (w *KernelWatcher) WatchKernelRoute(t *tomb.Tomb) error { + err := w.loadKernelRoute() + if err != nil { + return err + } + + ch := make(chan netlink.RouteUpdate) + err = netlink.RouteSubscribe(ch, nil) + if err != nil { + return err + } + for { + select { + case <-t.Dying(): + w.log.Infof("Kernel Watcher asked to stop") + return nil + case update := <-ch: + w.log.Debugf("kernel update: %s", update) + if update.Table == syscall.RT_TABLE_MAIN && + (update.Protocol == syscall.RTPROT_KERNEL || update.Protocol == syscall.RTPROT_BOOT) { + // TODO: handle ipPool deletion. RTM_DELROUTE message + // can belong to previously valid ipPool. + if w.ipam.GetPrefixIPPool(update.Dst) == nil { + continue + } + isWithdrawal := false + switch update.Type { + case syscall.RTM_DELROUTE: + isWithdrawal = true + case syscall.RTM_NEWROUTE: + default: + w.log.Debugf("unhandled rtm type: %d", update.Type) + continue + } + ip4, ip6 := common.GetBGPSpecAddresses(w.nodeBGPSpec) + path, err := common.MakePath(update.Dst.String(), isWithdrawal, ip4, ip6, 0, 0) + if err != nil { + return err + } + w.log.Debugf("made path from kernel update: %s", path) + common.SendEvent(common.CalicoVppEvent{ + Type: common.BGPPathAdded, + New: path, + }) + } else if update.Table == syscall.RT_TABLE_LOCAL { + // This means the interface address is updated + // Some routes we injected may be deleted by the kernel + // Reload routes from BGP RIB and inject again + ip, _, _ := net.ParseCIDR(update.Dst.String()) + if ip.To4() == nil { + common.SendEvent(common.CalicoVppEvent{Type: common.BGPReloadIP6}) + } else { + common.SendEvent(common.CalicoVppEvent{Type: common.BGPReloadIP4}) + } + } + } + } +} + +func (w *KernelWatcher) loadKernelRoute() error { + filter := &netlink.Route{ + Table: syscall.RT_TABLE_MAIN, + } + list, err := netlink.RouteListFiltered(netlink.FAMILY_V4, filter, netlink.RT_FILTER_TABLE) + if err != nil { + return err + } + for _, route := range list { + if route.Dst == nil { + continue + } + if w.ipam.GetPrefixIPPool(route.Dst) == nil { + continue + } + if route.Protocol == syscall.RTPROT_KERNEL || route.Protocol == syscall.RTPROT_BOOT { + ip4, ip6 := common.GetBGPSpecAddresses(w.nodeBGPSpec) + path, err := common.MakePath(route.Dst.String(), false /* isWithdrawal */, ip4, ip6, 0, 0) + if err != nil { + return err + } + w.log.Tracef("made path from kernel route: %s", path) + common.SendEvent(common.CalicoVppEvent{ + Type: common.BGPPathAdded, + New: path, + }) + } + } + return nil +} + +func (w *KernelWatcher) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { + w.nodeBGPSpec = nodeBGPSpec +} + +func NewKernelWatcher(ipam IpamCache, log *logrus.Entry) *KernelWatcher { + w := KernelWatcher{ + log: log, + ipam: ipam, + } + return &w +} diff --git a/calico-vpp-agent/watchers/nodes_watcher.go b/calico-vpp-agent/watchers/nodes_watcher.go index 19a404bc9..e0fa20334 100644 --- a/calico-vpp-agent/watchers/nodes_watcher.go +++ b/calico-vpp-agent/watchers/nodes_watcher.go @@ -19,33 +19,35 @@ import ( "context" "fmt" "net" + "strings" "time" "github.com/pkg/errors" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" + //oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" + "github.com/projectcalico/api/pkg/lib/numorstring" calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/options" - "github.com/projectcalico/calico/libcalico-go/lib/watch" "github.com/sirupsen/logrus" tomb "gopkg.in/tomb.v2" "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" "github.com/projectcalico/vpp-dataplane/config/config" + "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/proto" "github.com/projectcalico/vpp-dataplane/vpplink" ) type NodeWatcher struct { log *logrus.Entry - nodeStatesByName map[string]oldv3.Node - gotOurNodeBGPchan chan oldv3.NodeBGPSpec + nodeStatesByName map[string]common.LocalNodeSpec + gotOurNodeBGPchan chan common.LocalNodeSpec didWeGetOurNodeBGP bool clientv3 calicov3cli.Interface vpp *vpplink.VppLink - watcher watch.Interface currentWatchRevision string + nodeEventChan chan common.CalicoVppEvent } func (w *NodeWatcher) initialNodeSync() (resourceVersion string, err error) { @@ -63,7 +65,15 @@ func (w *NodeWatcher) initialNodeSync() (resourceVersion string, err error) { nodeNames := make(map[string]bool) for _, calicoNode := range nodes.Items { nodeNames[calicoNode.Name] = true - err = w.handleNodeUpdate(&calicoNode, true /* isAdd */) + err = w.handleNodeUpdate( + &common.LocalNodeSpec{ + ASNumber: calicoNode.Spec.BGP.ASNumber, + Name: calicoNode.Name, + IPv4Address: calicoNode.Spec.BGP.IPv4Address, + IPv6Address: calicoNode.Spec.BGP.IPv6Address, + Labels: calicoNode.Labels, + WireguardPublicKey: calicoNode.Status.WireguardPublicKey, + }, true /* isAdd */) if err != nil { return "", err } @@ -82,7 +92,7 @@ func (w *NodeWatcher) initialNodeSync() (resourceVersion string, err error) { func (w *NodeWatcher) WatchNodes(t *tomb.Tomb) error { for t.Alive() { w.currentWatchRevision = "" - err := w.resyncAndCreateWatcher() + err := w.resync() if err != nil { w.log.Error(err) goto restart @@ -91,45 +101,56 @@ func (w *NodeWatcher) WatchNodes(t *tomb.Tomb) error { select { case <-t.Dying(): w.log.Infof("Nodes Watcher asked to stop") - w.cleanExistingWatcher() return nil - case update, ok := <-w.watcher.ResultChan(): - if !ok { - w.log.Debug("nodes watch channel closed, restarting...") - err := w.resyncAndCreateWatcher() - if err != nil { - goto restart + case event := <-w.nodeEventChan: + switch event.Type { + case common.NodeRouteUpdate: + node := event.New.(*proto.RouteUpdate) + localNodeSpec := &common.LocalNodeSpec{ + Name: node.DstNodeName, + Labels: node.Labels, + WireguardPublicKey: node.WireguardPublicKey, } - continue - } - switch update.Type { - case watch.Error: - w.log.Debug("nodes watch returned, restarting") - goto restart - case watch.Modified, watch.Added: - err := w.handleNodeUpdate(update.Object.(*oldv3.Node), true /* isAdd */) + if node.Asnumber != "" { + asn, err := numorstring.ASNumberFromString(node.Asnumber) + if err != nil { + return err + } + localNodeSpec.ASNumber = &asn + } + if strings.Contains(node.Dst, ":") { + localNodeSpec.IPv6Address = node.Dst + } else { + localNodeSpec.IPv4Address = node.Dst + } + err = w.handleNodeUpdate(localNodeSpec, true /* isAdd */) if err != nil { return err } - case watch.Deleted: - err := w.handleNodeUpdate(update.Previous.(*oldv3.Node), false /* isAdd */) + case common.NodeRouteDelete: + node := event.Old.(*common.NodeRouteRemove) + localNodeSpec := &common.LocalNodeSpec{Name: node.Name} + if strings.Contains(node.Dst, ":") { + localNodeSpec.IPv6Address = node.Dst + } else { + localNodeSpec.IPv4Address = node.Dst + } + err := w.handleNodeUpdate(localNodeSpec, false /* isAdd */) if err != nil { return err } } - } } restart: w.log.Debug("restarting nodes watcher...") - w.cleanExistingWatcher() time.Sleep(2 * time.Second) } return nil } -func (w *NodeWatcher) resyncAndCreateWatcher() error { +func (w *NodeWatcher) resync() error { if w.currentWatchRevision == "" { resourceVersion, err := w.initialNodeSync() if err != nil { @@ -137,38 +158,20 @@ func (w *NodeWatcher) resyncAndCreateWatcher() error { } w.currentWatchRevision = resourceVersion } - w.cleanExistingWatcher() - watcher, err := w.clientv3.Nodes().Watch( - context.Background(), - options.ListOptions{ResourceVersion: w.currentWatchRevision}, - ) - if err != nil { - return err - } - w.watcher = watcher return nil } -func (w *NodeWatcher) cleanExistingWatcher() { - if w.watcher != nil { - w.watcher.Stop() - w.log.Debug("Stopped watcher") - w.watcher = nil - } -} - -func (w *NodeWatcher) WaitForOurBGPSpec() *oldv3.NodeBGPSpec { +func (w *NodeWatcher) WaitForOurBGPSpec() *common.LocalNodeSpec { bgpspec := <-w.gotOurNodeBGPchan return &bgpspec } -func (w *NodeWatcher) handleNodeUpdate(nodeP *oldv3.Node, isAdd bool) (err error) { +func (w *NodeWatcher) handleNodeUpdate(node *common.LocalNodeSpec, isAdd bool) (err error) { // This ensures that nodes that don't have a BGP Spec are never present in the state map - if nodeP == nil || nodeP.Spec.BGP == nil { // No BGP config for this node + if node == nil { // No BGP config for this node return nil } - node := nodeP.DeepCopy() old, found := w.nodeStatesByName[node.Name] if isAdd { if found { @@ -178,10 +181,12 @@ func (w *NodeWatcher) handleNodeUpdate(nodeP *oldv3.Node, isAdd bool) (err error } w.nodeStatesByName[node.Name] = *node } else { - // This assumes that the old spec and the new spec are identical. if found { - err = w.onNodeDeleted(&old) - delete(w.nodeStatesByName, node.Name) + err = w.onNodeDeleted(&old, node) + if old.IPv4Address == "" && old.IPv6Address == "" { //both addresses deleted + w.log.Infof("deleted node %+v", node) + delete(w.nodeStatesByName, node.Name) + } } else { return fmt.Errorf("Node to delete not found") } @@ -189,11 +194,11 @@ func (w *NodeWatcher) handleNodeUpdate(nodeP *oldv3.Node, isAdd bool) (err error return err } -func (w *NodeWatcher) configureRemoteNodeSnat(node *oldv3.Node, isAdd bool) { - if node.Spec.BGP.IPv4Address != "" { - addr, _, err := net.ParseCIDR(node.Spec.BGP.IPv4Address) +func (w *NodeWatcher) configureRemoteNodeSnat(node *common.LocalNodeSpec, isAdd bool) { + if node.IPv4Address != "" { + addr, _, err := net.ParseCIDR(node.IPv4Address) if err != nil { - w.log.Errorf("cannot parse node address %s: %v", node.Spec.BGP.IPv4Address, err) + w.log.Errorf("cannot parse node address %s: %v", node.IPv4Address, err) } else { err = w.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(addr), isAdd) if err != nil { @@ -201,10 +206,10 @@ func (w *NodeWatcher) configureRemoteNodeSnat(node *oldv3.Node, isAdd bool) { } } } - if node.Spec.BGP.IPv6Address != "" { - addr, _, err := net.ParseCIDR(node.Spec.BGP.IPv6Address) + if node.IPv6Address != "" { + addr, _, err := net.ParseCIDR(node.IPv6Address) if err != nil { - w.log.Errorf("cannot parse node address %s: %v", node.Spec.BGP.IPv6Address, err) + w.log.Errorf("cannot parse node address %s: %v", node.IPv6Address, err) } else { err = w.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(addr), isAdd) if err != nil { @@ -214,7 +219,7 @@ func (w *NodeWatcher) configureRemoteNodeSnat(node *oldv3.Node, isAdd bool) { } } -func (w *NodeWatcher) onNodeDeleted(old *oldv3.Node) error { +func (w *NodeWatcher) onNodeDeleted(old *common.LocalNodeSpec, node *common.LocalNodeSpec) error { common.SendEvent(common.CalicoVppEvent{ Type: common.PeerNodeStateChanged, Old: old, @@ -224,6 +229,12 @@ func (w *NodeWatcher) onNodeDeleted(old *oldv3.Node) error { return NodeWatcherRestartError{} } + if node.IPv4Address != "" { + old.IPv4Address = "" + } + if node.IPv6Address != "" { + old.IPv6Address = "" + } w.configureRemoteNodeSnat(old, false /* isAdd */) return nil } @@ -234,11 +245,17 @@ func (e NodeWatcherRestartError) Error() string { return "node configuration changed, restarting" } -func (w *NodeWatcher) onNodeUpdated(old *oldv3.Node, node *oldv3.Node) (err error) { - w.log.Debugf("node comparison: old:%+v new:%+v", old.Spec.BGP, node.Spec.BGP) +func (w *NodeWatcher) onNodeUpdated(old *common.LocalNodeSpec, node *common.LocalNodeSpec) (err error) { + //w.log.Infof("node comparison: old:%+v new:%+v", old, node) - newV4IP, newV6IP := common.GetNodeSpecAddresses(node) - oldV4IP, oldV6IP := common.GetNodeSpecAddresses(old) + newV4IP, newV6IP := node.IPv4Address, node.IPv6Address + oldV4IP, oldV6IP := old.IPv4Address, old.IPv6Address + if node.IPv4Address == "" { + node.IPv4Address = old.IPv4Address + } + if node.IPv6Address == "" { + node.IPv6Address = old.IPv6Address + } // This is used by the routing server to process Wireguard key updates // As a result we only send an event when a node is updated, not when it is added or deleted @@ -248,7 +265,8 @@ func (w *NodeWatcher) onNodeUpdated(old *oldv3.Node, node *oldv3.Node) (err erro New: node, }) - change := common.GetStringChangeType(oldV4IP, newV4IP) | common.GetStringChangeType(oldV6IP, newV6IP) + // RouteUpdates contain either ipv4 or ipv6 address, so restart is needed when both change not just one + change := common.GetStringChangeType(oldV4IP, newV4IP) & common.GetStringChangeType(oldV6IP, newV6IP) if change&(common.ChangeDeleted|common.ChangeUpdated) != 0 && node.Name == config.NodeName { // restart if our BGP config changed return NodeWatcherRestartError{} @@ -261,12 +279,12 @@ func (w *NodeWatcher) onNodeUpdated(old *oldv3.Node, node *oldv3.Node) (err erro return nil } -func (w *NodeWatcher) onNodeAdded(node *oldv3.Node) (err error) { +func (w *NodeWatcher) onNodeAdded(node *common.LocalNodeSpec) (err error) { if node.Name == config.NodeName && !w.didWeGetOurNodeBGP { - nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(node.Spec.BGP) + nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(node) if nodeIP4 != nil || nodeIP6 != nil { /* We found a BGP Spec that seems valid enough */ - w.gotOurNodeBGPchan <- *node.Spec.BGP + w.gotOurNodeBGPchan <- *node w.didWeGetOurNodeBGP = true } } @@ -285,10 +303,12 @@ func NewNodeWatcher(vpp *vpplink.VppLink, clientv3 calicov3cli.Interface, log *l vpp: vpp, log: log, clientv3: clientv3, - nodeStatesByName: make(map[string]oldv3.Node), - gotOurNodeBGPchan: make(chan oldv3.NodeBGPSpec, 10), + nodeStatesByName: make(map[string]common.LocalNodeSpec), + gotOurNodeBGPchan: make(chan common.LocalNodeSpec, 10), didWeGetOurNodeBGP: false, + nodeEventChan: make(chan common.CalicoVppEvent), } - + reg := common.RegisterHandler(w.nodeEventChan, "node watcher events") + reg.ExpectEvents(common.NodeRouteUpdate, common.NodeRouteDelete) return &w } diff --git a/calico-vpp-agent/watchers/peers_watcher.go b/calico-vpp-agent/watchers/peers_watcher.go index 0b7e23feb..a293e790e 100644 --- a/calico-vpp-agent/watchers/peers_watcher.go +++ b/calico-vpp-agent/watchers/peers_watcher.go @@ -30,7 +30,6 @@ import ( "k8s.io/client-go/kubernetes" calicov3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/projectcalico/calico/libcalico-go/lib/backend/api" calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/options" @@ -48,7 +47,7 @@ type PeerWatcher struct { // Subcomponent for accessing and watching secrets (that hold BGP passwords). secretWatcher *secretWatcher - nodeStatesByName map[string]oldv3.Node + nodeStatesByName map[string]common.LocalNodeSpec peerWatcherEventChan chan common.CalicoVppEvent BGPConf *calicov3.BGPConfigurationSpec watcher watch.Interface @@ -64,7 +63,7 @@ type bgpPeer struct { // selectsNode determines whether or not the selector mySelector // matches the labels on the given node. -func selectsNode(mySelector string, n *oldv3.Node) (bool, error) { +func selectsNode(mySelector string, n *common.LocalNodeSpec) (bool, error) { // No node selector means that the selector matches the node. if len(mySelector) == 0 { return true, nil @@ -89,11 +88,11 @@ func (w *PeerWatcher) shouldPeer(peer *calicov3.BGPPeer) bool { return true } -func (w *PeerWatcher) getAsNumber(node *oldv3.Node) uint32 { - if node.Spec.BGP.ASNumber == nil { +func (w *PeerWatcher) getAsNumber(node *common.LocalNodeSpec) uint32 { + if node.ASNumber == nil { return uint32(*w.BGPConf.ASNumber) } else { - return uint32(*node.Spec.BGP.ASNumber) + return uint32(*node.ASNumber) } } @@ -110,24 +109,20 @@ func (w *PeerWatcher) selectPeers(peerSelector string) map[string]uint32 { w.log.Errorf("Error in peerSelector matching: %v", err) } if matches { - if node.Spec.BGP != nil && node.Spec.BGP.IPv4Address != "" && - w.currentCalicoNode().Spec.BGP != nil && - w.currentCalicoNode().Spec.BGP.IPv4Address != "" { - ad, _, err := net.ParseCIDR(node.Spec.BGP.IPv4Address) + if node.IPv4Address != "" && w.currentCalicoNode().IPv4Address != "" { + ad, _, err := net.ParseCIDR(node.IPv4Address) if err == nil { ipAsn[ad.String()] = w.getAsNumber(&node) } else { - w.log.Warnf("Can't parse node IPv4: %s", node.Spec.BGP.IPv4Address) + w.log.Warnf("Can't parse node IPv4: %s", node.IPv4Address) } } - if node.Spec.BGP != nil && node.Spec.BGP.IPv6Address != "" && - w.currentCalicoNode().Spec.BGP != nil && - w.currentCalicoNode().Spec.BGP.IPv6Address != "" { - ad, _, err := net.ParseCIDR(node.Spec.BGP.IPv6Address) + if node.IPv6Address != "" && w.currentCalicoNode().IPv6Address != "" { + ad, _, err := net.ParseCIDR(node.IPv6Address) if err == nil { ipAsn[ad.String()] = w.getAsNumber(&node) } else { - w.log.Warnf("Can't parse node IPv6: %s", node.Spec.BGP.IPv6Address) + w.log.Warnf("Can't parse node IPv6: %s", node.IPv6Address) } } } @@ -135,7 +130,7 @@ func (w *PeerWatcher) selectPeers(peerSelector string) map[string]uint32 { return ipAsn } -func (w *PeerWatcher) currentCalicoNode() *oldv3.Node { +func (w *PeerWatcher) currentCalicoNode() *common.LocalNodeSpec { node := w.nodeStatesByName[config.NodeName] return &node } @@ -179,8 +174,8 @@ func (w *PeerWatcher) WatchBGPPeers(t *tomb.Tomb) error { /* Note: we will only receive events we ask for when registering the chan */ switch evt.Type { case common.PeerNodeStateChanged: - old, _ := evt.Old.(*oldv3.Node) - new, _ := evt.New.(*oldv3.Node) + old, _ := evt.Old.(*common.LocalNodeSpec) + new, _ := evt.New.(*common.LocalNodeSpec) if old != nil { delete(w.nodeStatesByName, old.Name) } @@ -518,7 +513,7 @@ func NewPeerWatcher(clientv3 calicov3cli.Interface, k8sclient *kubernetes.Client var err error w := PeerWatcher{ clientv3: clientv3, - nodeStatesByName: make(map[string]oldv3.Node), + nodeStatesByName: make(map[string]common.LocalNodeSpec), log: log, peerWatcherEventChan: make(chan common.CalicoVppEvent, common.ChanSize), } diff --git a/calico-vpp-agent/watchers/prefix_watcher.go b/calico-vpp-agent/watchers/prefix_watcher.go index 80493face..2e6c47e2a 100644 --- a/calico-vpp-agent/watchers/prefix_watcher.go +++ b/calico-vpp-agent/watchers/prefix_watcher.go @@ -24,7 +24,6 @@ import ( "github.com/golang/protobuf/ptypes" bgpapi "github.com/osrg/gobgp/api" "github.com/pkg/errors" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" "github.com/projectcalico/calico/libcalico-go/lib/backend/model" "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" "github.com/projectcalico/vpp-dataplane/config/config" @@ -38,7 +37,7 @@ import ( type PrefixWatcher struct { log *logrus.Entry client *calicocli.Client - nodeBGPSpec *oldv3.NodeBGPSpec + nodeBGPSpec *common.LocalNodeSpec } const ( @@ -249,7 +248,7 @@ func (w *PrefixWatcher) updateOneBGPPath(path *bgpapi.Path) error { return nil } -func (w *PrefixWatcher) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (w *PrefixWatcher) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { w.nodeBGPSpec = nodeBGPSpec } diff --git a/calico-vpp-agent/watchers/srv6_localsid_watcher.go b/calico-vpp-agent/watchers/srv6_localsid_watcher.go index 7cd627f32..b4858f00a 100644 --- a/calico-vpp-agent/watchers/srv6_localsid_watcher.go +++ b/calico-vpp-agent/watchers/srv6_localsid_watcher.go @@ -6,7 +6,6 @@ import ( "time" "github.com/pkg/errors" - oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/ipam" cnet "github.com/projectcalico/calico/libcalico-go/lib/net" @@ -24,7 +23,7 @@ type LocalSIDWatcher struct { log *logrus.Entry vpp *vpplink.VppLink clientv3 calicov3cli.Interface - nodeBGPSpec *oldv3.NodeBGPSpec + nodeBGPSpec *common.LocalNodeSpec } const ( @@ -106,7 +105,7 @@ func (p *LocalSIDWatcher) getSidFromPool(ipnet string) (newSidAddr ip_types.IP6A return newSidAddr, nil } -func (w *LocalSIDWatcher) SetOurBGPSpec(nodeBGPSpec *oldv3.NodeBGPSpec) { +func (w *LocalSIDWatcher) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { w.nodeBGPSpec = nodeBGPSpec } From a67e1bcfbc5f4dc0a905547b87eaf8d5326932a7 Mon Sep 17 00:00:00 2001 From: hedi bouattour Date: Wed, 12 Oct 2022 15:41:49 +0000 Subject: [PATCH 2/3] agent: remove node watcher server and replace in policy server --- calico-vpp-agent/cmd/calico_vpp_dataplane.go | 9 +- calico-vpp-agent/cni/cni_node_test.go | 12 +- calico-vpp-agent/cni/pod_annotations.go | 4 +- calico-vpp-agent/common/common.go | 73 ++-- calico-vpp-agent/common/pubsub.go | 3 - .../connectivity/connectivity_server.go | 24 +- calico-vpp-agent/connectivity/ipsec.go | 8 +- calico-vpp-agent/policy/host_endpoint.go | 8 +- calico-vpp-agent/policy/policy_server.go | 252 +++++++++++--- calico-vpp-agent/policy/workload_endpoint.go | 2 +- calico-vpp-agent/routing/routing_server.go | 1 - calico-vpp-agent/watchers/kernel_watcher.go | 138 -------- calico-vpp-agent/watchers/nodes_watcher.go | 314 ------------------ calico-vpp-agent/watchers/peers_watcher.go | 18 +- 14 files changed, 261 insertions(+), 605 deletions(-) delete mode 100644 calico-vpp-agent/watchers/kernel_watcher.go delete mode 100644 calico-vpp-agent/watchers/nodes_watcher.go diff --git a/calico-vpp-agent/cmd/calico_vpp_dataplane.go b/calico-vpp-agent/cmd/calico_vpp_dataplane.go index e61136710..66f7a735d 100644 --- a/calico-vpp-agent/cmd/calico_vpp_dataplane.go +++ b/calico-vpp-agent/cmd/calico_vpp_dataplane.go @@ -128,7 +128,6 @@ func main() { routeWatcher := watchers.NewRouteWatcher(common.VppManagerInfo.FakeNextHopIP4, common.VppManagerInfo.FakeNextHopIP6) linkWatcher := watchers.NewLinkWatcher(common.VppManagerInfo.UplinkStatuses) bgpConfigurationWatcher := watchers.NewBGPConfigurationWatcher(clientv3, log.WithFields(logrus.Fields{"subcomponent": "bgp-conf-watch"})) - nodeWatcher := watchers.NewNodeWatcher(vpp, clientv3, log.WithFields(logrus.Fields{"subcomponent": "node-watcher"})) prefixWatcher := watchers.NewPrefixWatcher(client, log.WithFields(logrus.Fields{"subcomponent": "prefix-watcher"})) peerWatcher := watchers.NewPeerWatcher(clientv3, k8sclient, log.WithFields(logrus.Fields{"subcomponent": "peer-watcher"})) netWatcher := watchers.NewNetWatcher(vpp, log.WithFields(logrus.Fields{"component": "net-watcher"})) @@ -154,15 +153,15 @@ func main() { routingServer.SetBGPConf(bgpConf) serviceServer.SetBGPConf(bgpConf) + Go(policyServer.ServePolicy) log.Infof("Waiting for our node's BGP spec...") - Go(nodeWatcher.WatchNodes) - ourBGPSpec := nodeWatcher.WaitForOurBGPSpec() + felixConfig := policyServer.WaitForFelixConfig() + ourBGPSpec := policyServer.WaitForOurBGPSpec() prefixWatcher.SetOurBGPSpec(ourBGPSpec) connectivityServer.SetOurBGPSpec(ourBGPSpec) routingServer.SetOurBGPSpec(ourBGPSpec) serviceServer.SetOurBGPSpec(ourBGPSpec) - policyServer.SetOurBGPSpec(ourBGPSpec) localSIDWatcher.SetOurBGPSpec(ourBGPSpec) /** @@ -176,8 +175,6 @@ func main() { <-netWatcher.InSync log.Infof("Networks synced") } - Go(policyServer.ServePolicy) - felixConfig := policyServer.WaitForFelixConfig() cniServer.SetFelixConfig(felixConfig) connectivityServer.SetFelixConfig(felixConfig) diff --git a/calico-vpp-agent/cni/cni_node_test.go b/calico-vpp-agent/cni/cni_node_test.go index 279426744..1c1d58913 100644 --- a/calico-vpp-agent/cni/cni_node_test.go +++ b/calico-vpp-agent/cni/cni_node_test.go @@ -564,7 +564,7 @@ var _ = Describe("Node-related functionality of CNI", func() { addedNodePublicKey := "public-key-for-added-node" // max 32 characters due to VPP binapi connectivityServer.ForceNodeAddition(common.LocalNodeSpec{ - Name: AddedNodeName, + Name: AddedNodeName, WireguardPublicKey: base64.StdEncoding.EncodeToString([]byte(addedNodePublicKey)), }, net.ParseIP(AddedNodeIP)) err = connectivityServer.UpdateIPConnectivity(&common.NodeConnectivity{ @@ -580,11 +580,11 @@ var _ = Describe("Node-related functionality of CNI", func() { Expect(err).ToNot(HaveOccurred(), "can't find wireguard tunnel interface") wgTunnel, err := vpp.GetWireguardTunnel(wireguardSwIfIndex) Expect(err).ToNot(HaveOccurred(), "can't get wireguard tunnel from VPP") + Expect(wgTunnel.Port).To(Equal(uint16(felixConfig.WireguardListeningPort)), "incorrectly set wireguard listening port") Expect(wgTunnel.Addr).To(Equal(net.ParseIP(ThisNodeIP).To4()), "incorrectly set IP address of this node's wireguard tunnel interface") - By("checking wireguard tunnel interface attributes (Unnumbered)") assertUnnumberedInterface(wireguardSwIfIndex, "wireguard tunnel interface", vpp) @@ -1013,9 +1013,13 @@ func assertNextNodeLink(node, linkedNextNode string, vpp *vpplink.VppLink) int { } func configureBGPNodeIPAddresses(connectivityServer *connectivity.ConnectivityServer) { + ip4, ip4net, _ := net.ParseCIDR(ThisNodeIP + "/24") + ip4net.IP = ip4 + ip6, ip6net, _ := net.ParseCIDR(ThisNodeIPv6 + "/128") + ip6net.IP = ip6 connectivityServer.SetOurBGPSpec(&common.LocalNodeSpec{ - IPv4Address: ThisNodeIP + "/24", - IPv6Address: ThisNodeIPv6 + "/128", + IPv4Address: ip4net, + IPv6Address: ip6net, }) } diff --git a/calico-vpp-agent/cni/pod_annotations.go b/calico-vpp-agent/cni/pod_annotations.go index ed5179dfa..6b863cd9a 100644 --- a/calico-vpp-agent/cni/pod_annotations.go +++ b/calico-vpp-agent/cni/pod_annotations.go @@ -55,7 +55,7 @@ func (s *Server) ParsePortSpec(value string) (ifPortConfigs *storage.LocalIfPort return nil, fmt.Errorf("Please specify a port or a port range e.g. '1234-5678'") } - start, err := strconv.ParseInt(portParts[0], 10, 16) + start, err := strconv.ParseUint(portParts[0], 10, 16) if err != nil { return nil, errors.Wrapf(err, "Error parsing port %s", portParts[0]) } @@ -63,7 +63,7 @@ func (s *Server) ParsePortSpec(value string) (ifPortConfigs *storage.LocalIfPort ifPortConfigs.End = uint16(start) if len(portParts) == 2 { - end, err := strconv.ParseInt(portParts[1], 10, 16) + end, err := strconv.ParseUint(portParts[1], 10, 16) if err != nil { return nil, errors.Wrapf(err, "Error parsing end port %s", portParts[1]) } diff --git a/calico-vpp-agent/common/common.go b/calico-vpp-agent/common/common.go index 9aa1a10bf..889b99535 100644 --- a/calico-vpp-agent/common/common.go +++ b/calico-vpp-agent/common/common.go @@ -55,17 +55,13 @@ type PolicyServerIpam interface { IPNetNeedsSNAT(prefix *net.IPNet) bool GetPrefixIPPool(prefix *net.IPNet) *proto.IPAMPool } -type NodeRouteRemove struct { - Dst string - Name string -} type LocalNodeSpec struct { ASNumber *numorstring.ASNumber Labels map[string]string Name string - IPv4Address string - IPv6Address string + IPv4Address *net.IPNet + IPv6Address *net.IPNet WireguardPublicKey string } @@ -430,6 +426,17 @@ const ( ChangeUpdated ChangeType = 4 ) +func GetIpNetChangeType(old, new *net.IPNet) ChangeType { + var oldStr, newStr string + if old != nil { + oldStr = old.IP.String() + } + if new != nil { + newStr = new.IP.String() + } + return GetStringChangeType(oldStr, newStr) +} + func GetStringChangeType(old, new string) ChangeType { if old == new && new == "" { return ChangeSame @@ -466,56 +473,14 @@ type SRv6Tunnel struct { Priority uint32 } -func GetBGPSpecAddresses(nodeBGPSpec *LocalNodeSpec) (*net.IP, *net.IP) { - var ip4 *net.IP - var ip6 *net.IP - if nodeBGPSpec.IPv4Address != "" { - addr, _, err := net.ParseCIDR(nodeBGPSpec.IPv4Address) - if err == nil { - ip4 = &addr - } - } - if nodeBGPSpec.IPv6Address != "" { - addr, _, err := net.ParseCIDR(nodeBGPSpec.IPv6Address) - if err == nil { - ip6 = &addr - } - } - return ip4, ip6 -} - -func GetBGPSpecIPNet(nodeBGPSpec *LocalNodeSpec) (ip4 *net.IPNet, ip6 *net.IPNet) { - if nodeBGPSpec.IPv4Address != "" { - _, ipNet, err := net.ParseCIDR(nodeBGPSpec.IPv4Address) - if err == nil { - ip4 = ipNet - } +func GetBGPSpecAddresses(nodeBGPSpec *LocalNodeSpec) (ip4 *net.IP, ip6 *net.IP) { + if nodeBGPSpec.IPv4Address != nil { + ip4 = &nodeBGPSpec.IPv4Address.IP } - if nodeBGPSpec.IPv6Address != "" { - _, ipNet, err := net.ParseCIDR(nodeBGPSpec.IPv6Address) - if err == nil { - ip6 = ipNet - } + if nodeBGPSpec.IPv6Address != nil { + ip6 = &nodeBGPSpec.IPv6Address.IP } - return ip4, ip6 -} - -func GetNodeSpecAddresses(node *LocalNodeSpec) (string, string) { - nodeIP4 := "" - nodeIP6 := "" - if node.IPv4Address != "" { - addr, _, err := net.ParseCIDR(node.IPv4Address) - if err == nil { - nodeIP4 = addr.String() - } - } - if node.IPv6Address != "" { - addr, _, err := net.ParseCIDR(node.IPv6Address) - if err == nil { - nodeIP6 = addr.String() - } - } - return nodeIP4, nodeIP6 + return } func FormatBGPConfiguration(conf *calicov3.BGPConfigurationSpec) string { diff --git a/calico-vpp-agent/common/pubsub.go b/calico-vpp-agent/common/pubsub.go index ebe22d39b..8768949a0 100644 --- a/calico-vpp-agent/common/pubsub.go +++ b/calico-vpp-agent/common/pubsub.go @@ -64,9 +64,6 @@ const ( IpamPoolUpdate CalicoVppEventType = "IpamPoolUpdate" IpamPoolRemove CalicoVppEventType = "IpamPoolRemove" - - NodeRouteUpdate CalicoVppEventType = "NodeRouteUpdate" - NodeRouteDelete CalicoVppEventType = "NodeRouteDelete" ) var ( diff --git a/calico-vpp-agent/connectivity/connectivity_server.go b/calico-vpp-agent/connectivity/connectivity_server.go index d2c4b9008..8f7fce790 100644 --- a/calico-vpp-agent/connectivity/connectivity_server.go +++ b/calico-vpp-agent/connectivity/connectivity_server.go @@ -39,8 +39,8 @@ type ConnectivityServer struct { connectivityMap map[string]common.NodeConnectivity policyServerIpam common.PolicyServerIpam Clientv3 calicov3cli.Interface - nodeBGPSpec *common.LocalNodeSpec - vpp *vpplink.VppLink + nodeBGPSpec *common.LocalNodeSpec + vpp *vpplink.VppLink felixConfig *felixConfig.Config nodeByAddr map[string]common.LocalNodeSpec @@ -123,7 +123,7 @@ func (s *ConnectivityServer) GetNodeIPs() (ip4 *net.IP, ip6 *net.IP) { } func (s *ConnectivityServer) GetNodeIPNet(isv6 bool) *net.IPNet { - ip4, ip6 := common.GetBGPSpecIPNet(s.nodeBGPSpec) + ip4, ip6 := s.nodeBGPSpec.IPv4Address, s.nodeBGPSpec.IPv6Address if isv6 { return ip6 } else { @@ -177,21 +177,19 @@ func (s *ConnectivityServer) ServeConnectivity(t *tomb.Tomb) error { old, _ := evt.Old.(*common.LocalNodeSpec) new, _ := evt.New.(*common.LocalNodeSpec) if old != nil { - oldV4IP, oldV6IP := common.GetNodeSpecAddresses(old) - if oldV4IP != "" { - delete(s.nodeByAddr, oldV4IP) + if old.IPv4Address != nil { + delete(s.nodeByAddr, old.IPv4Address.IP.String()) } - if oldV6IP != "" { - delete(s.nodeByAddr, oldV6IP) + if old.IPv6Address != nil { + delete(s.nodeByAddr, old.IPv6Address.IP.String()) } } if new != nil { - newV4IP, newV6IP := common.GetNodeSpecAddresses(new) - if newV4IP != "" { - s.nodeByAddr[newV4IP] = *new + if new.IPv4Address != nil { + s.nodeByAddr[new.IPv4Address.IP.String()] = *new } - if newV6IP != "" { - s.nodeByAddr[newV6IP] = *new + if new.IPv6Address != nil { + s.nodeByAddr[new.IPv6Address.IP.String()] = *new } } if old != nil && new != nil { diff --git a/calico-vpp-agent/connectivity/ipsec.go b/calico-vpp-agent/connectivity/ipsec.go index d45a18f57..259f913a3 100644 --- a/calico-vpp-agent/connectivity/ipsec.go +++ b/calico-vpp-agent/connectivity/ipsec.go @@ -332,9 +332,11 @@ func (p *IpsecProvider) forceOtherNodeIp4(addr net.IP) (ip4 net.IP, err error) { if otherNode == nil { return nil, fmt.Errorf("Didnt find an ip4 for ip %s", addr.String()) } - nodeIP, _, err := net.ParseCIDR(otherNode.IPv4Address) - if err != nil { - return nil, errors.Wrapf(err, "Didnt find an ip4 for ip %s", addr.String()) + var nodeIP net.IP + if otherNode.IPv4Address != nil { + nodeIP = otherNode.IPv4Address.IP + } else { + return nil, fmt.Errorf("didn't find an ip4") } return nodeIP, nil } diff --git a/calico-vpp-agent/policy/host_endpoint.go b/calico-vpp-agent/policy/host_endpoint.go index 1a8787223..1a85cd43a 100644 --- a/calico-vpp-agent/policy/host_endpoint.go +++ b/calico-vpp-agent/policy/host_endpoint.go @@ -172,10 +172,10 @@ func (h *HostEndpoint) getTapPolicies(state *PolicyState) (conf *types.Interface } if len(conf.IngressPolicyIDs) > 0 { conf.IngressPolicyIDs = append([]uint32{h.server.workloadsToHostPolicy.VppID}, conf.IngressPolicyIDs...) - conf.IngressPolicyIDs = append([]uint32{h.server.failSafePolicy.VppID}, conf.IngressPolicyIDs...) + conf.IngressPolicyIDs = append([]uint32{h.server.failSafePolicyId}, conf.IngressPolicyIDs...) } if len(conf.EgressPolicyIDs) > 0 { - conf.EgressPolicyIDs = append([]uint32{h.server.failSafePolicy.VppID}, conf.EgressPolicyIDs...) + conf.EgressPolicyIDs = append([]uint32{h.server.failSafePolicyId}, conf.EgressPolicyIDs...) } return conf, nil } @@ -244,10 +244,10 @@ func (h *HostEndpoint) getForwardPolicies(state *PolicyState) (conf *types.Inter } } if len(conf.EgressPolicyIDs) > 0 { - conf.EgressPolicyIDs = append([]uint32{h.server.allowToHostPolicy.VppID}, conf.EgressPolicyIDs...) + conf.EgressPolicyIDs = append([]uint32{h.server.allowToHostPolicyId}, conf.EgressPolicyIDs...) } if len(conf.IngressPolicyIDs) > 0 { - conf.IngressPolicyIDs = append([]uint32{h.server.allowToHostPolicy.VppID}, conf.IngressPolicyIDs...) + conf.IngressPolicyIDs = append([]uint32{h.server.allowToHostPolicyId}, conf.IngressPolicyIDs...) } return conf, ownPolicies, nil } diff --git a/calico-vpp-agent/policy/policy_server.go b/calico-vpp-agent/policy/policy_server.go index cc677e335..48cafc3e2 100644 --- a/calico-vpp-agent/policy/policy_server.go +++ b/calico-vpp-agent/policy/policy_server.go @@ -27,6 +27,7 @@ import ( "sync" "github.com/pkg/errors" + "github.com/projectcalico/api/pkg/lib/numorstring" felixConfig "github.com/projectcalico/calico/felix/config" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" @@ -56,6 +57,12 @@ const ( StateInSync ) +type NodeWatcherRestartError struct{} + +func (e NodeWatcherRestartError) Error() string { + return "node configuration changed, restarting" +} + // Server holds all the data required to configure the policies defined by felix in VPP type Server struct { log *logrus.Entry @@ -71,17 +78,17 @@ type Server struct { pendingState *PolicyState /* failSafe policies allow traffic on some ports irrespective of the policy */ - failSafePolicy *Policy + failSafePolicyId uint32 /* workloadToHost may drop traffic that goes from the pods to the host */ workloadsToHostIPSet *IPSet workloadsToHostPolicy *Policy /* always allow traffic coming from host to the pods (for healthchecks and so on) */ - allowFromHostPolicy *Policy + allowFromHostPolicyId uint32 /* allow traffic between uplink/tunnels and tap interfaces */ - allowToHostPolicy *Policy - ip4 *net.IP - ip6 *net.IP - interfacesMap map[string]interfaceDetails + allowToHostPolicyId uint32 + ip4 *net.IP + ip6 *net.IP + interfacesMap map[string]interfaceDetails policyServerEventChan chan common.CalicoVppEvent networkDefinitions map[string]*watchers.NetworkDefinition @@ -93,15 +100,12 @@ type Server struct { felixConfigChan chan *felixConfig.Config felixConfig *felixConfig.Config - ippoolmap map[string]proto.IPAMPoolUpdate - ippoolLock sync.RWMutex - hosts map[string]string -} + ippoolmap map[string]proto.IPAMPoolUpdate + ippoolLock sync.RWMutex + hostNameByDst map[string]string -func (s *Server) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { - ip4, ip6 := common.GetBGPSpecAddresses(nodeBGPSpec) - s.ip4 = ip4 - s.ip6 = ip6 + nodeStatesByName map[string]*common.LocalNodeSpec + gotOurNodeBGPchan chan common.LocalNodeSpec } // NewServer creates a policy server @@ -129,8 +133,15 @@ func NewPolicyServer(vpp *vpplink.VppLink, log *logrus.Entry) (*Server, error) { felixConfigChan: make(chan *felixConfig.Config), felixConfig: felixConfig.New(), - ippoolmap: make(map[string]proto.IPAMPoolUpdate), - hosts: make(map[string]string), + ippoolmap: make(map[string]proto.IPAMPoolUpdate), + hostNameByDst: make(map[string]string), + + nodeStatesByName: make(map[string]*common.LocalNodeSpec), + gotOurNodeBGPchan: make(chan common.LocalNodeSpec), + + failSafePolicyId: types.InvalidID, + allowFromHostPolicyId: types.InvalidID, + allowToHostPolicyId: types.InvalidID, } reg := common.RegisterHandler(server.policyServerEventChan, "policy server events") @@ -425,15 +436,14 @@ func (s *Server) ServePolicy(t *tomb.Tomb) error { listener.Close() os.RemoveAll(config.FelixDataplaneSocket) }() - - err = s.createAllowFromHostPolicy() - if err != nil { - return errors.Wrap(err, "Error in createAllowFromHostPolicy") - } err = s.createEndpointToHostPolicy() if err != nil { return errors.Wrap(err, "Error in createEndpointToHostPolicy") } + err = s.createAllowFromHostPolicy() + if err != nil { + return errors.Wrap(err, "Error in createAllowFromHostPolicy") + } err = s.createAllowToHostPolicy() if err != nil { return errors.Wrap(err, "Error in createAllowToHostPolicy") @@ -480,9 +490,14 @@ func (s *Server) ServePolicy(t *tomb.Tomb) error { } err = s.handleFelixUpdate(msg) if err != nil { - s.log.WithError(err).Error("Error processing update from felix, restarting") - // TODO: Restart VPP as well? State is left over there... - break innerLoop + switch err.(type) { + case NodeWatcherRestartError: + return err + default: + s.log.WithError(err).Error("Error processing update from felix, restarting") + // TODO: Restart VPP as well? State is left over there... + break innerLoop + } } } } @@ -1104,26 +1119,160 @@ func (s *Server) handleRouteUpdate(msg *proto.RouteUpdate, pending bool) (err er // node update (local or remote host) if msg.Type == proto.RouteType_REMOTE_HOST || msg.Type == proto.RouteType_LOCAL_HOST { s.log.Infof("received node update msg from felix: %+v", msg) - s.hosts[msg.Dst] = msg.DstNodeName - common.SendEvent(common.CalicoVppEvent{ - Type: common.NodeRouteUpdate, - New: msg, - }) + s.hostNameByDst[msg.Dst] = msg.DstNodeName + localNodeSpec := &common.LocalNodeSpec{ + Name: msg.DstNodeName, + Labels: msg.Labels, + WireguardPublicKey: msg.WireguardPublicKey, + } + if msg.Asnumber != "" { + asn, err := numorstring.ASNumberFromString(msg.Asnumber) + if err != nil { + return err + } + localNodeSpec.ASNumber = &asn + } + ip, ipnet, err := net.ParseCIDR(msg.Dst) + if err != nil { + return err + } + ipnet.IP = ip + if ipnet.IP.To4() == nil { + localNodeSpec.IPv6Address = ipnet + } else { + localNodeSpec.IPv4Address = ipnet + } + old, found := s.nodeStatesByName[localNodeSpec.Name] + if found { + err = s.onNodeUpdated(old, localNodeSpec) + } else { + err = s.onNodeAdded(localNodeSpec) + } + s.nodeStatesByName[localNodeSpec.Name] = localNodeSpec + if err != nil { + return err + } } return nil } func (s *Server) handleRouteRemove(msg *proto.RouteRemove, pending bool) (err error) { // cannot directly tell which type of route that is, so look in map? - if name, ok := s.hosts[msg.Dst]; ok { + if name, ok := s.hostNameByDst[msg.Dst]; ok { s.log.Infof("received node remove msg from felix: %+v: %s", msg, name) - common.SendEvent(common.CalicoVppEvent{ - Type: common.NodeRouteDelete, - Old: &common.NodeRouteRemove{ - Dst: msg.Dst, - Name: name, - }, - }) + localNodeSpec := &common.LocalNodeSpec{Name: name} + ip, ipnet, err := net.ParseCIDR(msg.Dst) + if err != nil { + return err + } + ipnet.IP = ip + if ipnet.IP.To4() == nil { + localNodeSpec.IPv6Address = ipnet + } else { + localNodeSpec.IPv4Address = ipnet + } + old, found := s.nodeStatesByName[localNodeSpec.Name] + if found { + err = s.onNodeDeleted(old, localNodeSpec) + if err != nil { + return err + } + } else { + return fmt.Errorf("Node to delete not found") + } + } + return nil +} + +func (s *Server) onNodeUpdated(old *common.LocalNodeSpec, node *common.LocalNodeSpec) (err error) { + if node.IPv4Address == nil { + node.IPv4Address = old.IPv4Address + } + if node.IPv6Address == nil { + node.IPv6Address = old.IPv6Address + } + + // This is used by the routing server to process Wireguard key updates + // As a result we only send an event when a node is updated, not when it is added or deleted + common.SendEvent(common.CalicoVppEvent{ + Type: common.PeerNodeStateChanged, + Old: old, + New: node, + }) + change := common.GetIpNetChangeType(old.IPv4Address, node.IPv4Address) | common.GetIpNetChangeType(old.IPv6Address, node.IPv6Address) + if change&(common.ChangeDeleted|common.ChangeUpdated) != 0 && node.Name == config.NodeName { + // restart if our BGP config changed + return NodeWatcherRestartError{} + } + if change != common.ChangeSame { + s.configureRemoteNodeSnat(old, false /* isAdd */) + s.configureRemoteNodeSnat(node, true /* isAdd */) + } + + return nil +} + +func (s *Server) onNodeAdded(node *common.LocalNodeSpec) (err error) { + if node.Name == config.NodeName && + (node.IPv4Address != nil || node.IPv6Address != nil) { + if s.ip4 == nil && s.ip6 == nil { + /* We found a BGP Spec that seems valid enough */ + s.gotOurNodeBGPchan <- *node + } + if node.IPv4Address != nil { + s.ip4 = &node.IPv4Address.IP + } + if node.IPv6Address != nil { + s.ip6 = &node.IPv6Address.IP + } + s.createAllowFromHostPolicy() + s.createAllowToHostPolicy() + } + + common.SendEvent(common.CalicoVppEvent{ + Type: common.PeerNodeStateChanged, + New: node, + }) + s.configureRemoteNodeSnat(node, true /* isAdd */) + + return nil +} + +func (s *Server) configureRemoteNodeSnat(node *common.LocalNodeSpec, isAdd bool) { + if node.IPv4Address != nil { + err := s.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(node.IPv4Address.IP), isAdd) + if err != nil { + s.log.Errorf("error configuring snat prefix for current node (%v): %v", node.IPv4Address.IP, err) + } + } + if node.IPv6Address != nil { + err := s.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(node.IPv6Address.IP), isAdd) + if err != nil { + s.log.Errorf("error configuring snat prefix for current node (%v): %v", node.IPv6Address.IP, err) + } + } +} + +func (s *Server) onNodeDeleted(old *common.LocalNodeSpec, node *common.LocalNodeSpec) error { + common.SendEvent(common.CalicoVppEvent{ + Type: common.PeerNodeStateChanged, + Old: old, + }) + if old.Name == config.NodeName { + // restart if our BGP config changed + return NodeWatcherRestartError{} + } + + if node.IPv4Address != nil { + old.IPv4Address = nil + } + if node.IPv6Address != nil { + old.IPv6Address = nil + } + s.configureRemoteNodeSnat(old, false /* isAdd */) + if old.IPv4Address == nil && old.IPv6Address == nil { //both addresses deleted + s.log.Infof("deleted node %+v", node) + delete(s.nodeStatesByName, node.Name) } return nil } @@ -1274,6 +1423,11 @@ func (s *Server) IPNetNeedsSNAT(prefix *net.IPNet) bool { } +func (s *Server) WaitForOurBGPSpec() *common.LocalNodeSpec { + bgpspec := <-s.gotOurNodeBGPchan + return &bgpspec +} + // contains returns true if the IPPool contains 'prefix' func contains(pool *proto.IPAMPoolUpdate, prefix *net.IPNet) (bool, error) { _, poolCIDR, _ := net.ParseCIDR(pool.Pool.Cidr) // this field is validated so this should never error @@ -1419,13 +1573,14 @@ func (s *Server) createAllowToHostPolicy() (err error) { r_out.Rule.SrcNet = append(r_out.Rule.SrcNet, *common.FullyQualified(*s.ip6)) } - s.allowToHostPolicy = &Policy{ + allowToHostPolicy := &Policy{ Policy: &types.Policy{}, - VppID: types.InvalidID, + VppID: s.allowToHostPolicyId, } - s.allowToHostPolicy.InboundRules = append(s.allowToHostPolicy.InboundRules, r_out) - s.allowToHostPolicy.OutboundRules = append(s.allowToHostPolicy.OutboundRules, r_in) - err = s.allowToHostPolicy.Create(s.vpp, nil) + allowToHostPolicy.InboundRules = append(allowToHostPolicy.InboundRules, r_out) + allowToHostPolicy.OutboundRules = append(allowToHostPolicy.OutboundRules, r_in) + err = allowToHostPolicy.Create(s.vpp, nil) + s.allowToHostPolicyId = allowToHostPolicy.VppID return errors.Wrap(err, "cannot create policy to allow traffic to host") } @@ -1446,12 +1601,13 @@ func (s *Server) createAllowFromHostPolicy() (err error) { r.Rule.SrcNet = append(r.Rule.SrcNet, *common.FullyQualified(*s.ip6)) } - s.allowFromHostPolicy = &Policy{ + allowFromHostPolicy := &Policy{ Policy: &types.Policy{}, - VppID: types.InvalidID, + VppID: s.allowFromHostPolicyId, } - s.allowFromHostPolicy.InboundRules = append(s.allowFromHostPolicy.InboundRules, r) - err = s.allowFromHostPolicy.Create(s.vpp, nil) + allowFromHostPolicy.InboundRules = append(allowFromHostPolicy.InboundRules, r) + err = allowFromHostPolicy.Create(s.vpp, nil) + s.allowFromHostPolicyId = allowFromHostPolicy.VppID return errors.Wrap(err, "cannot create policy to allow traffic from host") } @@ -1515,7 +1671,7 @@ func (s *Server) createEndpointToHostPolicy( /*may be return*/ ) (err error) { func (s *Server) createFailSafePolicies() (err error) { failSafePol := &Policy{ Policy: &types.Policy{}, - VppID: types.InvalidID, + VppID: s.failSafePolicyId, } failSafeInboundRules, err := getfailSafeRules(s.felixConfig.FailsafeInboundHostPorts) @@ -1534,7 +1690,7 @@ func (s *Server) createFailSafePolicies() (err error) { if err != nil { return err } - s.failSafePolicy = failSafePol + s.failSafePolicyId = failSafePol.VppID return nil } diff --git a/calico-vpp-agent/policy/workload_endpoint.go b/calico-vpp-agent/policy/workload_endpoint.go index 988fcfbcb..5e96ffe7e 100644 --- a/calico-vpp-agent/policy/workload_endpoint.go +++ b/calico-vpp-agent/policy/workload_endpoint.go @@ -121,7 +121,7 @@ func (w *WorkloadEndpoint) getPolicies(state *PolicyState, network string) (conf conf.ProfileIDs = append(conf.ProfileIDs, prof.VppID) } if len(conf.IngressPolicyIDs) > 0 { - conf.IngressPolicyIDs = append([]uint32{w.server.allowFromHostPolicy.VppID}, conf.IngressPolicyIDs...) + conf.IngressPolicyIDs = append([]uint32{w.server.allowFromHostPolicyId}, conf.IngressPolicyIDs...) } return conf, nil } diff --git a/calico-vpp-agent/routing/routing_server.go b/calico-vpp-agent/routing/routing_server.go index c1b462309..addaef462 100644 --- a/calico-vpp-agent/routing/routing_server.go +++ b/calico-vpp-agent/routing/routing_server.go @@ -177,7 +177,6 @@ func (s *Server) getGoBGPGlobalConfig() (*bgpapi.Global, error) { asn := s.nodeBGPSpec.ASNumber if asn == nil { asn = s.BGPConf.ASNumber - s.log.Infof("herere %+v", asn) } nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(s.nodeBGPSpec) diff --git a/calico-vpp-agent/watchers/kernel_watcher.go b/calico-vpp-agent/watchers/kernel_watcher.go deleted file mode 100644 index d32105972..000000000 --- a/calico-vpp-agent/watchers/kernel_watcher.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (C) 2020 Cisco Systems Inc. -// -// 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 watchers - -import ( - "net" - "syscall" - - "github.com/sirupsen/logrus" - "github.com/vishvananda/netlink" - tomb "gopkg.in/tomb.v2" - - "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" -) - -type KernelWatcher struct { - log *logrus.Entry - ipam IpamCache - nodeBGPSpec *common.LocalNodeSpec -} - -// watchKernelRoute receives netlink route update notification and announces -// kernel/boot routes using BGP. -// TODO: should we leverage this to update VPP routes as well? -func (w *KernelWatcher) WatchKernelRoute(t *tomb.Tomb) error { - err := w.loadKernelRoute() - if err != nil { - return err - } - - ch := make(chan netlink.RouteUpdate) - err = netlink.RouteSubscribe(ch, nil) - if err != nil { - return err - } - for { - select { - case <-t.Dying(): - w.log.Infof("Kernel Watcher asked to stop") - return nil - case update := <-ch: - w.log.Debugf("kernel update: %s", update) - if update.Table == syscall.RT_TABLE_MAIN && - (update.Protocol == syscall.RTPROT_KERNEL || update.Protocol == syscall.RTPROT_BOOT) { - // TODO: handle ipPool deletion. RTM_DELROUTE message - // can belong to previously valid ipPool. - if w.ipam.GetPrefixIPPool(update.Dst) == nil { - continue - } - isWithdrawal := false - switch update.Type { - case syscall.RTM_DELROUTE: - isWithdrawal = true - case syscall.RTM_NEWROUTE: - default: - w.log.Debugf("unhandled rtm type: %d", update.Type) - continue - } - ip4, ip6 := common.GetBGPSpecAddresses(w.nodeBGPSpec) - path, err := common.MakePath(update.Dst.String(), isWithdrawal, ip4, ip6, 0, 0) - if err != nil { - return err - } - w.log.Debugf("made path from kernel update: %s", path) - common.SendEvent(common.CalicoVppEvent{ - Type: common.BGPPathAdded, - New: path, - }) - } else if update.Table == syscall.RT_TABLE_LOCAL { - // This means the interface address is updated - // Some routes we injected may be deleted by the kernel - // Reload routes from BGP RIB and inject again - ip, _, _ := net.ParseCIDR(update.Dst.String()) - if ip.To4() == nil { - common.SendEvent(common.CalicoVppEvent{Type: common.BGPReloadIP6}) - } else { - common.SendEvent(common.CalicoVppEvent{Type: common.BGPReloadIP4}) - } - } - } - } -} - -func (w *KernelWatcher) loadKernelRoute() error { - filter := &netlink.Route{ - Table: syscall.RT_TABLE_MAIN, - } - list, err := netlink.RouteListFiltered(netlink.FAMILY_V4, filter, netlink.RT_FILTER_TABLE) - if err != nil { - return err - } - for _, route := range list { - if route.Dst == nil { - continue - } - if w.ipam.GetPrefixIPPool(route.Dst) == nil { - continue - } - if route.Protocol == syscall.RTPROT_KERNEL || route.Protocol == syscall.RTPROT_BOOT { - ip4, ip6 := common.GetBGPSpecAddresses(w.nodeBGPSpec) - path, err := common.MakePath(route.Dst.String(), false /* isWithdrawal */, ip4, ip6, 0, 0) - if err != nil { - return err - } - w.log.Tracef("made path from kernel route: %s", path) - common.SendEvent(common.CalicoVppEvent{ - Type: common.BGPPathAdded, - New: path, - }) - } - } - return nil -} - -func (w *KernelWatcher) SetOurBGPSpec(nodeBGPSpec *common.LocalNodeSpec) { - w.nodeBGPSpec = nodeBGPSpec -} - -func NewKernelWatcher(ipam IpamCache, log *logrus.Entry) *KernelWatcher { - w := KernelWatcher{ - log: log, - ipam: ipam, - } - return &w -} diff --git a/calico-vpp-agent/watchers/nodes_watcher.go b/calico-vpp-agent/watchers/nodes_watcher.go deleted file mode 100644 index e0fa20334..000000000 --- a/calico-vpp-agent/watchers/nodes_watcher.go +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright (C) 2019 Cisco Systems Inc. -// -// 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 watchers - -import ( - "context" - "fmt" - "net" - "strings" - "time" - - "github.com/pkg/errors" - //oldv3 "github.com/projectcalico/calico/libcalico-go/lib/apis/v3" - "github.com/projectcalico/api/pkg/lib/numorstring" - calicov3cli "github.com/projectcalico/calico/libcalico-go/lib/clientv3" - "github.com/projectcalico/calico/libcalico-go/lib/options" - "github.com/sirupsen/logrus" - tomb "gopkg.in/tomb.v2" - - "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/common" - "github.com/projectcalico/vpp-dataplane/config/config" - "github.com/projectcalico/vpp-dataplane/calico-vpp-agent/proto" - "github.com/projectcalico/vpp-dataplane/vpplink" -) - -type NodeWatcher struct { - log *logrus.Entry - - nodeStatesByName map[string]common.LocalNodeSpec - gotOurNodeBGPchan chan common.LocalNodeSpec - didWeGetOurNodeBGP bool - - clientv3 calicov3cli.Interface - vpp *vpplink.VppLink - - currentWatchRevision string - nodeEventChan chan common.CalicoVppEvent -} - -func (w *NodeWatcher) initialNodeSync() (resourceVersion string, err error) { - // TODO: Get and watch only ourselves if there is no mesh - w.log.Info("Syncing nodes...") - nodes, err := w.clientv3.Nodes().List( - context.Background(), - options.ListOptions{ - ResourceVersion: w.currentWatchRevision, - }, - ) - if err != nil { - return "", errors.Wrap(err, "error listing nodes") - } - nodeNames := make(map[string]bool) - for _, calicoNode := range nodes.Items { - nodeNames[calicoNode.Name] = true - err = w.handleNodeUpdate( - &common.LocalNodeSpec{ - ASNumber: calicoNode.Spec.BGP.ASNumber, - Name: calicoNode.Name, - IPv4Address: calicoNode.Spec.BGP.IPv4Address, - IPv6Address: calicoNode.Spec.BGP.IPv6Address, - Labels: calicoNode.Labels, - WireguardPublicKey: calicoNode.Status.WireguardPublicKey, - }, true /* isAdd */) - if err != nil { - return "", err - } - } - for nodeName, node := range w.nodeStatesByName { - if _, found := nodeNames[nodeName]; !found { - err = w.handleNodeUpdate(&node, false /* isAdd */) - if err != nil { - return "", err - } - } - } - return nodes.ResourceVersion, nil -} - -func (w *NodeWatcher) WatchNodes(t *tomb.Tomb) error { - for t.Alive() { - w.currentWatchRevision = "" - err := w.resync() - if err != nil { - w.log.Error(err) - goto restart - } - for { - select { - case <-t.Dying(): - w.log.Infof("Nodes Watcher asked to stop") - return nil - case event := <-w.nodeEventChan: - switch event.Type { - case common.NodeRouteUpdate: - node := event.New.(*proto.RouteUpdate) - localNodeSpec := &common.LocalNodeSpec{ - Name: node.DstNodeName, - Labels: node.Labels, - WireguardPublicKey: node.WireguardPublicKey, - } - if node.Asnumber != "" { - asn, err := numorstring.ASNumberFromString(node.Asnumber) - if err != nil { - return err - } - localNodeSpec.ASNumber = &asn - } - if strings.Contains(node.Dst, ":") { - localNodeSpec.IPv6Address = node.Dst - } else { - localNodeSpec.IPv4Address = node.Dst - } - err = w.handleNodeUpdate(localNodeSpec, true /* isAdd */) - if err != nil { - return err - } - case common.NodeRouteDelete: - node := event.Old.(*common.NodeRouteRemove) - localNodeSpec := &common.LocalNodeSpec{Name: node.Name} - if strings.Contains(node.Dst, ":") { - localNodeSpec.IPv6Address = node.Dst - } else { - localNodeSpec.IPv4Address = node.Dst - } - err := w.handleNodeUpdate(localNodeSpec, false /* isAdd */) - if err != nil { - return err - } - } - } - } - - restart: - w.log.Debug("restarting nodes watcher...") - time.Sleep(2 * time.Second) - } - return nil -} - -func (w *NodeWatcher) resync() error { - if w.currentWatchRevision == "" { - resourceVersion, err := w.initialNodeSync() - if err != nil { - return err - } - w.currentWatchRevision = resourceVersion - } - return nil -} - -func (w *NodeWatcher) WaitForOurBGPSpec() *common.LocalNodeSpec { - bgpspec := <-w.gotOurNodeBGPchan - return &bgpspec -} - -func (w *NodeWatcher) handleNodeUpdate(node *common.LocalNodeSpec, isAdd bool) (err error) { - // This ensures that nodes that don't have a BGP Spec are never present in the state map - if node == nil { // No BGP config for this node - return nil - } - - old, found := w.nodeStatesByName[node.Name] - if isAdd { - if found { - err = w.onNodeUpdated(&old, node) - } else { - err = w.onNodeAdded(node) - } - w.nodeStatesByName[node.Name] = *node - } else { - if found { - err = w.onNodeDeleted(&old, node) - if old.IPv4Address == "" && old.IPv6Address == "" { //both addresses deleted - w.log.Infof("deleted node %+v", node) - delete(w.nodeStatesByName, node.Name) - } - } else { - return fmt.Errorf("Node to delete not found") - } - } - return err -} - -func (w *NodeWatcher) configureRemoteNodeSnat(node *common.LocalNodeSpec, isAdd bool) { - if node.IPv4Address != "" { - addr, _, err := net.ParseCIDR(node.IPv4Address) - if err != nil { - w.log.Errorf("cannot parse node address %s: %v", node.IPv4Address, err) - } else { - err = w.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(addr), isAdd) - if err != nil { - w.log.Errorf("error configuring snat prefix for current node (%v): %v", addr, err) - } - } - } - if node.IPv6Address != "" { - addr, _, err := net.ParseCIDR(node.IPv6Address) - if err != nil { - w.log.Errorf("cannot parse node address %s: %v", node.IPv6Address, err) - } else { - err = w.vpp.CnatAddDelSnatPrefix(common.ToMaxLenCIDR(addr), isAdd) - if err != nil { - w.log.Errorf("error configuring snat prefix for current node (%v): %v", addr, err) - } - } - } -} - -func (w *NodeWatcher) onNodeDeleted(old *common.LocalNodeSpec, node *common.LocalNodeSpec) error { - common.SendEvent(common.CalicoVppEvent{ - Type: common.PeerNodeStateChanged, - Old: old, - }) - if old.Name == config.NodeName { - // restart if our BGP config changed - return NodeWatcherRestartError{} - } - - if node.IPv4Address != "" { - old.IPv4Address = "" - } - if node.IPv6Address != "" { - old.IPv6Address = "" - } - w.configureRemoteNodeSnat(old, false /* isAdd */) - return nil -} - -type NodeWatcherRestartError struct{} - -func (e NodeWatcherRestartError) Error() string { - return "node configuration changed, restarting" -} - -func (w *NodeWatcher) onNodeUpdated(old *common.LocalNodeSpec, node *common.LocalNodeSpec) (err error) { - //w.log.Infof("node comparison: old:%+v new:%+v", old, node) - - newV4IP, newV6IP := node.IPv4Address, node.IPv6Address - oldV4IP, oldV6IP := old.IPv4Address, old.IPv6Address - if node.IPv4Address == "" { - node.IPv4Address = old.IPv4Address - } - if node.IPv6Address == "" { - node.IPv6Address = old.IPv6Address - } - - // This is used by the routing server to process Wireguard key updates - // As a result we only send an event when a node is updated, not when it is added or deleted - common.SendEvent(common.CalicoVppEvent{ - Type: common.PeerNodeStateChanged, - Old: old, - New: node, - }) - - // RouteUpdates contain either ipv4 or ipv6 address, so restart is needed when both change not just one - change := common.GetStringChangeType(oldV4IP, newV4IP) & common.GetStringChangeType(oldV6IP, newV6IP) - if change&(common.ChangeDeleted|common.ChangeUpdated) != 0 && node.Name == config.NodeName { - // restart if our BGP config changed - return NodeWatcherRestartError{} - } - if change != common.ChangeSame { - w.configureRemoteNodeSnat(old, false /* isAdd */) - w.configureRemoteNodeSnat(node, true /* isAdd */) - } - - return nil -} - -func (w *NodeWatcher) onNodeAdded(node *common.LocalNodeSpec) (err error) { - if node.Name == config.NodeName && !w.didWeGetOurNodeBGP { - nodeIP4, nodeIP6 := common.GetBGPSpecAddresses(node) - if nodeIP4 != nil || nodeIP6 != nil { - /* We found a BGP Spec that seems valid enough */ - w.gotOurNodeBGPchan <- *node - w.didWeGetOurNodeBGP = true - } - } - - common.SendEvent(common.CalicoVppEvent{ - Type: common.PeerNodeStateChanged, - New: node, - }) - w.configureRemoteNodeSnat(node, true /* isAdd */) - - return nil -} - -func NewNodeWatcher(vpp *vpplink.VppLink, clientv3 calicov3cli.Interface, log *logrus.Entry) *NodeWatcher { - w := NodeWatcher{ - vpp: vpp, - log: log, - clientv3: clientv3, - nodeStatesByName: make(map[string]common.LocalNodeSpec), - gotOurNodeBGPchan: make(chan common.LocalNodeSpec, 10), - didWeGetOurNodeBGP: false, - nodeEventChan: make(chan common.CalicoVppEvent), - } - reg := common.RegisterHandler(w.nodeEventChan, "node watcher events") - reg.ExpectEvents(common.NodeRouteUpdate, common.NodeRouteDelete) - return &w -} diff --git a/calico-vpp-agent/watchers/peers_watcher.go b/calico-vpp-agent/watchers/peers_watcher.go index a293e790e..ecddbaf83 100644 --- a/calico-vpp-agent/watchers/peers_watcher.go +++ b/calico-vpp-agent/watchers/peers_watcher.go @@ -109,21 +109,11 @@ func (w *PeerWatcher) selectPeers(peerSelector string) map[string]uint32 { w.log.Errorf("Error in peerSelector matching: %v", err) } if matches { - if node.IPv4Address != "" && w.currentCalicoNode().IPv4Address != "" { - ad, _, err := net.ParseCIDR(node.IPv4Address) - if err == nil { - ipAsn[ad.String()] = w.getAsNumber(&node) - } else { - w.log.Warnf("Can't parse node IPv4: %s", node.IPv4Address) - } + if node.IPv4Address != nil && w.currentCalicoNode().IPv4Address != nil { + ipAsn[node.IPv4Address.IP.String()] = w.getAsNumber(&node) } - if node.IPv6Address != "" && w.currentCalicoNode().IPv6Address != "" { - ad, _, err := net.ParseCIDR(node.IPv6Address) - if err == nil { - ipAsn[ad.String()] = w.getAsNumber(&node) - } else { - w.log.Warnf("Can't parse node IPv6: %s", node.IPv6Address) - } + if node.IPv6Address != nil && w.currentCalicoNode().IPv6Address != nil { + ipAsn[node.IPv6Address.IP.String()] = w.getAsNumber(&node) } } } From a05ca3d471b8c061754385f943c945a65cdeb324 Mon Sep 17 00:00:00 2001 From: hedibouattour Date: Wed, 30 Nov 2022 12:07:20 +0000 Subject: [PATCH 3/3] agent: use hostmetadata and wireguardkeyupsgs from felix --- calico-vpp-agent/cni/cni_node_test.go | 4 +- calico-vpp-agent/cni/cni_server.go | 5 +- calico-vpp-agent/common/common.go | 12 +- calico-vpp-agent/common/pubsub.go | 2 + .../connectivity/connectivity_server.go | 23 +- calico-vpp-agent/connectivity/wireguard.go | 16 +- calico-vpp-agent/policy/messages.go | 12 +- calico-vpp-agent/policy/policy_server.go | 162 ++-- calico-vpp-agent/proto/felixbackend.pb.go | 702 +++++++++++------- calico-vpp-agent/proto/felixbackend.proto | 18 + 10 files changed, 573 insertions(+), 383 deletions(-) diff --git a/calico-vpp-agent/cni/cni_node_test.go b/calico-vpp-agent/cni/cni_node_test.go index 1c1d58913..4aa640a43 100644 --- a/calico-vpp-agent/cni/cni_node_test.go +++ b/calico-vpp-agent/cni/cni_node_test.go @@ -564,9 +564,9 @@ var _ = Describe("Node-related functionality of CNI", func() { addedNodePublicKey := "public-key-for-added-node" // max 32 characters due to VPP binapi connectivityServer.ForceNodeAddition(common.LocalNodeSpec{ - Name: AddedNodeName, - WireguardPublicKey: base64.StdEncoding.EncodeToString([]byte(addedNodePublicKey)), + Name: AddedNodeName, }, net.ParseIP(AddedNodeIP)) + connectivityServer.ForceWGPublicKeyAddition(AddedNodeName, base64.StdEncoding.EncodeToString([]byte(addedNodePublicKey))) err = connectivityServer.UpdateIPConnectivity(&common.NodeConnectivity{ Dst: *ipNet(AddedNodeIP + "/24"), NextHop: net.ParseIP(AddedNodeIP), // wireguard impl uses nexthop as node IP diff --git a/calico-vpp-agent/cni/cni_server.go b/calico-vpp-agent/cni/cni_server.go index c0c4eb87f..78f940fe6 100644 --- a/calico-vpp-agent/cni/cni_server.go +++ b/calico-vpp-agent/cni/cni_server.go @@ -426,7 +426,10 @@ func (s *Server) cniServerEventLoop(t *tomb.Tomb) error { } func (s *Server) ServeCNI(t *tomb.Tomb) error { - syscall.Unlink(config.CNIServerSocket) + err := syscall.Unlink(config.CNIServerSocket) + if err != nil { + s.log.Warnf("unable to unlink cni server socket: %+v", err) + } socketListener, err := net.Listen("unix", config.CNIServerSocket) if err != nil { diff --git a/calico-vpp-agent/common/common.go b/calico-vpp-agent/common/common.go index 889b99535..67248a938 100644 --- a/calico-vpp-agent/common/common.go +++ b/calico-vpp-agent/common/common.go @@ -57,11 +57,15 @@ type PolicyServerIpam interface { } type LocalNodeSpec struct { - ASNumber *numorstring.ASNumber - Labels map[string]string + ASNumber *numorstring.ASNumber + Labels map[string]string + Name string + IPv4Address *net.IPNet + IPv6Address *net.IPNet +} + +type NodeWireguardPublicKey struct { Name string - IPv4Address *net.IPNet - IPv6Address *net.IPNet WireguardPublicKey string } diff --git a/calico-vpp-agent/common/pubsub.go b/calico-vpp-agent/common/pubsub.go index 8768949a0..7c90b615d 100644 --- a/calico-vpp-agent/common/pubsub.go +++ b/calico-vpp-agent/common/pubsub.go @@ -64,6 +64,8 @@ const ( IpamPoolUpdate CalicoVppEventType = "IpamPoolUpdate" IpamPoolRemove CalicoVppEventType = "IpamPoolRemove" + + WireguardPublicKeyChanged CalicoVppEventType = "WireguardPublicKeyChanged" ) var ( diff --git a/calico-vpp-agent/connectivity/connectivity_server.go b/calico-vpp-agent/connectivity/connectivity_server.go index 8f7fce790..612cc19b4 100644 --- a/calico-vpp-agent/connectivity/connectivity_server.go +++ b/calico-vpp-agent/connectivity/connectivity_server.go @@ -89,6 +89,7 @@ func NewConnectivityServer(vpp *vpplink.VppLink, policyServerIpam common.PolicyS common.IpamConfChanged, common.SRv6PolicyAdded, common.SRv6PolicyDeleted, + common.WireguardPublicKeyChanged, ) nDataThreads := common.FetchNDataThreads(vpp, log) @@ -173,6 +174,15 @@ func (s *ConnectivityServer) ServeConnectivity(t *tomb.Tomb) error { if err != nil { s.log.Errorf("Error while deleting connectivity %s", err) } + case common.WireguardPublicKeyChanged: + old, _ := evt.Old.(*common.NodeWireguardPublicKey) + new, _ := evt.New.(*common.NodeWireguardPublicKey) + s.providers[WIREGUARD].(*WireguardProvider).nodesToWGPublicKey[new.Name] = new.WireguardPublicKey + change := common.GetStringChangeType(old.WireguardPublicKey, new.WireguardPublicKey) + if change != common.ChangeSame { + s.log.Infof("connectivity(upd) WireguardPublicKey Changed (%s) %s->%s", old.Name, old.WireguardPublicKey, new.WireguardPublicKey) + s.updateAllIPConnectivity() + } case common.PeerNodeStateChanged: old, _ := evt.Old.(*common.LocalNodeSpec) new, _ := evt.New.(*common.LocalNodeSpec) @@ -192,13 +202,6 @@ func (s *ConnectivityServer) ServeConnectivity(t *tomb.Tomb) error { s.nodeByAddr[new.IPv6Address.IP.String()] = *new } } - if old != nil && new != nil { - change := common.GetStringChangeType(old.WireguardPublicKey, new.WireguardPublicKey) - if change != common.ChangeSame { - s.log.Infof("connectivity(upd) WireguardPublicKey Changed (%s) %s->%s", old.Name, old.WireguardPublicKey, new.WireguardPublicKey) - s.updateAllIPConnectivity() - } - } case common.FelixConfChanged: old, _ := evt.Old.(*felixConfig.Config) new, _ := evt.New.(*felixConfig.Config) @@ -375,3 +378,9 @@ func (s *ConnectivityServer) ForceProviderEnableDisable(providerType string, ena func (s *ConnectivityServer) ForceNodeAddition(newNode common.LocalNodeSpec, newNodeIP net.IP) { s.nodeByAddr[newNodeIP.String()] = newNode } + +// ForceWGPublicKeyAddition will add other node information as provided by calico configuration +// The usage is mainly for testing purposes. +func (s *ConnectivityServer) ForceWGPublicKeyAddition(newNode string, wgPublicKey string) { + s.providers[WIREGUARD].(*WireguardProvider).nodesToWGPublicKey[newNode] = wgPublicKey +} diff --git a/calico-vpp-agent/connectivity/wireguard.go b/calico-vpp-agent/connectivity/wireguard.go index e329e7e9a..1fce68ebb 100644 --- a/calico-vpp-agent/connectivity/wireguard.go +++ b/calico-vpp-agent/connectivity/wireguard.go @@ -31,8 +31,9 @@ import ( type WireguardProvider struct { *ConnectivityProviderData - wireguardTunnels map[string]*types.WireguardTunnel - wireguardPeers map[string]types.WireguardPeer + wireguardTunnels map[string]*types.WireguardTunnel + wireguardPeers map[string]types.WireguardPeer + nodesToWGPublicKey map[string]string } func NewWireguardProvider(d *ConnectivityProviderData) *WireguardProvider { @@ -40,6 +41,7 @@ func NewWireguardProvider(d *ConnectivityProviderData) *WireguardProvider { ConnectivityProviderData: d, wireguardTunnels: make(map[string]*types.WireguardTunnel), wireguardPeers: make(map[string]types.WireguardPeer), + nodesToWGPublicKey: make(map[string]string), } } @@ -49,7 +51,7 @@ func (p *WireguardProvider) Enabled(cn *common.NodeConnectivity) bool { return false } node := p.GetNodeByIp(cn.NextHop) - return node.WireguardPublicKey != "" + return p.nodesToWGPublicKey[node.Name] != "" } func (p *WireguardProvider) getWireguardPort() uint16 { @@ -62,14 +64,14 @@ func (p *WireguardProvider) getWireguardPort() uint16 { func (p *WireguardProvider) getNodePublicKey(cn *common.NodeConnectivity) ([]byte, error) { node := p.GetNodeByIp(cn.NextHop) - if node.WireguardPublicKey == "" { + if p.nodesToWGPublicKey[node.Name] == "" { return nil, fmt.Errorf("no public key for node=%s", node.Name) } - p.log.Infof("connectivity(add) Wireguard nodeName=%s pubKey=%s", node.Name, node.WireguardPublicKey) - key, err := base64.StdEncoding.DecodeString(node.WireguardPublicKey) + p.log.Infof("connectivity(add) Wireguard nodeName=%s pubKey=%s", node.Name, p.nodesToWGPublicKey[node.Name]) + key, err := base64.StdEncoding.DecodeString(p.nodesToWGPublicKey[node.Name]) if err != nil { - return nil, errors.Wrapf(err, "Error decoding wireguard public key %s", node.WireguardPublicKey) + return nil, errors.Wrapf(err, "Error decoding wireguard public key %s", p.nodesToWGPublicKey[node.Name]) } return key, nil } diff --git a/calico-vpp-agent/policy/messages.go b/calico-vpp-agent/policy/messages.go index 49df6ee49..8b66e5459 100644 --- a/calico-vpp-agent/policy/messages.go +++ b/calico-vpp-agent/policy/messages.go @@ -99,10 +99,14 @@ func (s *Server) RecvMessage(conn net.Conn) (msg interface{}, err error) { msg = payload.HostMetadataUpdate case *proto.ToDataplane_HostMetadataRemove: msg = payload.HostMetadataRemove - case *proto.ToDataplane_RouteUpdate: - msg = payload.RouteUpdate - case *proto.ToDataplane_RouteRemove: - msg = payload.RouteRemove + case *proto.ToDataplane_HostMetadataV4V6Update: + msg = payload.HostMetadataV4V6Update + case *proto.ToDataplane_HostMetadataV4V6Remove: + msg = payload.HostMetadataV4V6Remove + case *proto.ToDataplane_WireguardEndpointUpdate: + msg = payload.WireguardEndpointUpdate + case *proto.ToDataplane_WireguardEndpointRemove: + msg = payload.WireguardEndpointRemove case *proto.ToDataplane_IpamPoolUpdate: msg = payload.IpamPoolUpdate case *proto.ToDataplane_IpamPoolRemove: diff --git a/calico-vpp-agent/policy/policy_server.go b/calico-vpp-agent/policy/policy_server.go index 48cafc3e2..cd29c5712 100644 --- a/calico-vpp-agent/policy/policy_server.go +++ b/calico-vpp-agent/policy/policy_server.go @@ -100,11 +100,12 @@ type Server struct { felixConfigChan chan *felixConfig.Config felixConfig *felixConfig.Config - ippoolmap map[string]proto.IPAMPoolUpdate - ippoolLock sync.RWMutex - hostNameByDst map[string]string + ippoolmap map[string]proto.IPAMPoolUpdate + ippoolLock sync.RWMutex nodeStatesByName map[string]*common.LocalNodeSpec + nodeByWGPublicKey map[string]string + gotOurNodeBGPchan chan common.LocalNodeSpec } @@ -133,8 +134,7 @@ func NewPolicyServer(vpp *vpplink.VppLink, log *logrus.Entry) (*Server, error) { felixConfigChan: make(chan *felixConfig.Config), felixConfig: felixConfig.New(), - ippoolmap: make(map[string]proto.IPAMPoolUpdate), - hostNameByDst: make(map[string]string), + ippoolmap: make(map[string]proto.IPAMPoolUpdate), nodeStatesByName: make(map[string]*common.LocalNodeSpec), gotOurNodeBGPchan: make(chan common.LocalNodeSpec), @@ -556,6 +556,10 @@ func (s *Server) handleFelixUpdate(msg interface{}) (err error) { err = s.handleHostMetadataUpdate(m, pending) case *proto.HostMetadataRemove: err = s.handleHostMetadataRemove(m, pending) + case *proto.HostMetadataV4V6Update: + err = s.handleHostMetadataV4V6Update(m, pending) + case *proto.HostMetadataV4V6Remove: + err = s.handleHostMetadataV4V6Remove(m, pending) case *proto.IPAMPoolUpdate: err = s.handleIpamPoolUpdate(m, pending) case *proto.IPAMPoolRemove: @@ -570,10 +574,10 @@ func (s *Server) handleFelixUpdate(msg interface{}) (err error) { err = s.handleNamespaceRemove(m, pending) case *proto.GlobalBGPConfigUpdate: err = s.handleGlobalBGPConfigUpdate(m, pending) - case *proto.RouteUpdate: - err = s.handleRouteUpdate(m, pending) - case *proto.RouteRemove: - err = s.handleRouteRemove(m, pending) + case *proto.WireguardEndpointUpdate: + err = s.handleWireguardEndpointUpdate(m, pending) + case *proto.WireguardEndpointRemove: + err = s.handleWireguardEndpointRemove(m, pending) default: s.log.Warnf("Unhandled message from felix: %v", m) } @@ -1115,83 +1119,81 @@ func (s *Server) handleHostMetadataRemove(msg *proto.HostMetadataRemove, pending return nil } -func (s *Server) handleRouteUpdate(msg *proto.RouteUpdate, pending bool) (err error) { - // node update (local or remote host) - if msg.Type == proto.RouteType_REMOTE_HOST || msg.Type == proto.RouteType_LOCAL_HOST { - s.log.Infof("received node update msg from felix: %+v", msg) - s.hostNameByDst[msg.Dst] = msg.DstNodeName - localNodeSpec := &common.LocalNodeSpec{ - Name: msg.DstNodeName, - Labels: msg.Labels, - WireguardPublicKey: msg.WireguardPublicKey, - } - if msg.Asnumber != "" { - asn, err := numorstring.ASNumberFromString(msg.Asnumber) - if err != nil { - return err - } - localNodeSpec.ASNumber = &asn - } - ip, ipnet, err := net.ParseCIDR(msg.Dst) - if err != nil { - return err - } - ipnet.IP = ip - if ipnet.IP.To4() == nil { - localNodeSpec.IPv6Address = ipnet - } else { - localNodeSpec.IPv4Address = ipnet - } - old, found := s.nodeStatesByName[localNodeSpec.Name] - if found { - err = s.onNodeUpdated(old, localNodeSpec) - } else { - err = s.onNodeAdded(localNodeSpec) - } - s.nodeStatesByName[localNodeSpec.Name] = localNodeSpec +func (s *Server) handleHostMetadataV4V6Update(msg *proto.HostMetadataV4V6Update, pending bool) (err error) { + ip, ip4net, err := net.ParseCIDR(msg.Ipv4Addr) + if err != nil { + return err + } + ip4net.IP = ip + ip, ip6net, err := net.ParseCIDR(msg.Ipv6Addr) + if err != nil { + return err + } + ip6net.IP = ip + localNodeSpec := &common.LocalNodeSpec{ + Name: msg.Hostname, + Labels: msg.Labels, + IPv4Address: ip4net, + IPv6Address: ip6net, + } + if msg.Asnumber != "" { + asn, err := numorstring.ASNumberFromString(msg.Asnumber) if err != nil { return err } + localNodeSpec.ASNumber = &asn + } + + old, found := s.nodeStatesByName[localNodeSpec.Name] + if found { + err = s.onNodeUpdated(old, localNodeSpec) + } else { + err = s.onNodeAdded(localNodeSpec) + } + s.nodeStatesByName[localNodeSpec.Name] = localNodeSpec + if err != nil { + return err } return nil } -func (s *Server) handleRouteRemove(msg *proto.RouteRemove, pending bool) (err error) { - // cannot directly tell which type of route that is, so look in map? - if name, ok := s.hostNameByDst[msg.Dst]; ok { - s.log.Infof("received node remove msg from felix: %+v: %s", msg, name) - localNodeSpec := &common.LocalNodeSpec{Name: name} - ip, ipnet, err := net.ParseCIDR(msg.Dst) +func (s *Server) handleHostMetadataV4V6Remove(msg *proto.HostMetadataV4V6Remove, pending bool) (err error) { + localNodeSpec := &common.LocalNodeSpec{Name: msg.Hostname} + old, found := s.nodeStatesByName[localNodeSpec.Name] + if found { + err = s.onNodeDeleted(old, localNodeSpec) if err != nil { return err } - ipnet.IP = ip - if ipnet.IP.To4() == nil { - localNodeSpec.IPv6Address = ipnet - } else { - localNodeSpec.IPv4Address = ipnet - } - old, found := s.nodeStatesByName[localNodeSpec.Name] - if found { - err = s.onNodeDeleted(old, localNodeSpec) - if err != nil { - return err - } - } else { - return fmt.Errorf("Node to delete not found") - } + } else { + return fmt.Errorf("Node to delete not found") } return nil } -func (s *Server) onNodeUpdated(old *common.LocalNodeSpec, node *common.LocalNodeSpec) (err error) { - if node.IPv4Address == nil { - node.IPv4Address = old.IPv4Address - } - if node.IPv6Address == nil { - node.IPv6Address = old.IPv6Address +func (s *Server) handleWireguardEndpointUpdate(msg *proto.WireguardEndpointUpdate, pending bool) (err error) { + s.log.Infof("Received wireguard public key %+v", msg) + var old *common.NodeWireguardPublicKey + _, ok := s.nodeByWGPublicKey[msg.Hostname] + if ok { + old = &common.NodeWireguardPublicKey{Name: msg.Hostname, WireguardPublicKey: s.nodeByWGPublicKey[msg.Hostname]} + } else { + old = &common.NodeWireguardPublicKey{Name: msg.Hostname} } + new := &common.NodeWireguardPublicKey{Name: msg.Hostname, WireguardPublicKey: msg.PublicKey} + common.SendEvent(common.CalicoVppEvent{ + Type: common.WireguardPublicKeyChanged, + Old: old, + New: new, + }) + return nil +} + +func (s *Server) handleWireguardEndpointRemove(msg *proto.WireguardEndpointRemove, pending bool) (err error) { + return nil +} +func (s *Server) onNodeUpdated(old *common.LocalNodeSpec, node *common.LocalNodeSpec) (err error) { // This is used by the routing server to process Wireguard key updates // As a result we only send an event when a node is updated, not when it is added or deleted common.SendEvent(common.CalicoVppEvent{ @@ -1225,8 +1227,14 @@ func (s *Server) onNodeAdded(node *common.LocalNodeSpec) (err error) { if node.IPv6Address != nil { s.ip6 = &node.IPv6Address.IP } - s.createAllowFromHostPolicy() - s.createAllowToHostPolicy() + err = s.createAllowFromHostPolicy() + if err != nil { + return errors.Wrap(err, "Error in createAllowFromHostPolicy") + } + err = s.createAllowToHostPolicy() + if err != nil { + return errors.Wrap(err, "Error in createAllowToHostPolicy") + } } common.SendEvent(common.CalicoVppEvent{ @@ -1263,17 +1271,7 @@ func (s *Server) onNodeDeleted(old *common.LocalNodeSpec, node *common.LocalNode return NodeWatcherRestartError{} } - if node.IPv4Address != nil { - old.IPv4Address = nil - } - if node.IPv6Address != nil { - old.IPv6Address = nil - } s.configureRemoteNodeSnat(old, false /* isAdd */) - if old.IPv4Address == nil && old.IPv6Address == nil { //both addresses deleted - s.log.Infof("deleted node %+v", node) - delete(s.nodeStatesByName, node.Name) - } return nil } diff --git a/calico-vpp-agent/proto/felixbackend.pb.go b/calico-vpp-agent/proto/felixbackend.pb.go index 41f512579..c52c7b3f6 100644 --- a/calico-vpp-agent/proto/felixbackend.pb.go +++ b/calico-vpp-agent/proto/felixbackend.pb.go @@ -203,6 +203,8 @@ type ToDataplane struct { // *ToDataplane_ConfigUpdate // *ToDataplane_HostMetadataUpdate // *ToDataplane_HostMetadataRemove + // *ToDataplane_HostMetadataV4V6Update + // *ToDataplane_HostMetadataV4V6Remove // *ToDataplane_IpamPoolUpdate // *ToDataplane_IpamPoolRemove // *ToDataplane_ServiceAccountUpdate @@ -302,6 +304,12 @@ type ToDataplane_HostMetadataUpdate struct { type ToDataplane_HostMetadataRemove struct { HostMetadataRemove *HostMetadataRemove `protobuf:"bytes,18,opt,name=host_metadata_remove,json=hostMetadataRemove,proto3,oneof" json:"host_metadata_remove,omitempty"` } +type ToDataplane_HostMetadataV4V6Update struct { + HostMetadataV4V6Update *HostMetadataV4V6Update `protobuf:"bytes,37,opt,name=host_metadata_v4v6_update,json=hostMetadataV4v6Update,proto3,oneof" json:"host_metadata_v4v6_update,omitempty"` +} +type ToDataplane_HostMetadataV4V6Remove struct { + HostMetadataV4V6Remove *HostMetadataV4V6Remove `protobuf:"bytes,38,opt,name=host_metadata_v4v6_remove,json=hostMetadataV4v6Remove,proto3,oneof" json:"host_metadata_v4v6_remove,omitempty"` +} type ToDataplane_IpamPoolUpdate struct { IpamPoolUpdate *IPAMPoolUpdate `protobuf:"bytes,16,opt,name=ipam_pool_update,json=ipamPoolUpdate,proto3,oneof" json:"ipam_pool_update,omitempty"` } @@ -378,6 +386,8 @@ func (*ToDataplane_WorkloadEndpointRemove) isToDataplane_Payload() {} func (*ToDataplane_ConfigUpdate) isToDataplane_Payload() {} func (*ToDataplane_HostMetadataUpdate) isToDataplane_Payload() {} func (*ToDataplane_HostMetadataRemove) isToDataplane_Payload() {} +func (*ToDataplane_HostMetadataV4V6Update) isToDataplane_Payload() {} +func (*ToDataplane_HostMetadataV4V6Remove) isToDataplane_Payload() {} func (*ToDataplane_IpamPoolUpdate) isToDataplane_Payload() {} func (*ToDataplane_IpamPoolRemove) isToDataplane_Payload() {} func (*ToDataplane_ServiceAccountUpdate) isToDataplane_Payload() {} @@ -518,6 +528,20 @@ func (m *ToDataplane) GetHostMetadataRemove() *HostMetadataRemove { return nil } +func (m *ToDataplane) GetHostMetadataV4V6Update() *HostMetadataV4V6Update { + if x, ok := m.GetPayload().(*ToDataplane_HostMetadataV4V6Update); ok { + return x.HostMetadataV4V6Update + } + return nil +} + +func (m *ToDataplane) GetHostMetadataV4V6Remove() *HostMetadataV4V6Remove { + if x, ok := m.GetPayload().(*ToDataplane_HostMetadataV4V6Remove); ok { + return x.HostMetadataV4V6Remove + } + return nil +} + func (m *ToDataplane) GetIpamPoolUpdate() *IPAMPoolUpdate { if x, ok := m.GetPayload().(*ToDataplane_IpamPoolUpdate); ok { return x.IpamPoolUpdate @@ -676,6 +700,8 @@ func (*ToDataplane) XXX_OneofWrappers() []interface{} { (*ToDataplane_ConfigUpdate)(nil), (*ToDataplane_HostMetadataUpdate)(nil), (*ToDataplane_HostMetadataRemove)(nil), + (*ToDataplane_HostMetadataV4V6Update)(nil), + (*ToDataplane_HostMetadataV4V6Remove)(nil), (*ToDataplane_IpamPoolUpdate)(nil), (*ToDataplane_IpamPoolRemove)(nil), (*ToDataplane_ServiceAccountUpdate)(nil), @@ -3082,6 +3108,122 @@ func (m *WireguardStatusUpdate) GetIpVersion() IPVersion { return IPVersion_ANY } +type HostMetadataV4V6Update struct { + Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` + Ipv4Addr string `protobuf:"bytes,2,opt,name=ipv4_addr,json=ipv4Addr,proto3" json:"ipv4_addr,omitempty"` + Ipv6Addr string `protobuf:"bytes,3,opt,name=ipv6_addr,json=ipv6Addr,proto3" json:"ipv6_addr,omitempty"` + Asnumber string `protobuf:"bytes,4,opt,name=asnumber,proto3" json:"asnumber,omitempty"` + Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HostMetadataV4V6Update) Reset() { *m = HostMetadataV4V6Update{} } +func (m *HostMetadataV4V6Update) String() string { return proto.CompactTextString(m) } +func (*HostMetadataV4V6Update) ProtoMessage() {} +func (*HostMetadataV4V6Update) Descriptor() ([]byte, []int) { + return fileDescriptor_a792994fb90b9e3e, []int{40} +} +func (m *HostMetadataV4V6Update) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HostMetadataV4V6Update.Unmarshal(m, b) +} +func (m *HostMetadataV4V6Update) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HostMetadataV4V6Update.Marshal(b, m, deterministic) +} +func (m *HostMetadataV4V6Update) XXX_Merge(src proto.Message) { + xxx_messageInfo_HostMetadataV4V6Update.Merge(m, src) +} +func (m *HostMetadataV4V6Update) XXX_Size() int { + return xxx_messageInfo_HostMetadataV4V6Update.Size(m) +} +func (m *HostMetadataV4V6Update) XXX_DiscardUnknown() { + xxx_messageInfo_HostMetadataV4V6Update.DiscardUnknown(m) +} + +var xxx_messageInfo_HostMetadataV4V6Update proto.InternalMessageInfo + +func (m *HostMetadataV4V6Update) GetHostname() string { + if m != nil { + return m.Hostname + } + return "" +} + +func (m *HostMetadataV4V6Update) GetIpv4Addr() string { + if m != nil { + return m.Ipv4Addr + } + return "" +} + +func (m *HostMetadataV4V6Update) GetIpv6Addr() string { + if m != nil { + return m.Ipv6Addr + } + return "" +} + +func (m *HostMetadataV4V6Update) GetAsnumber() string { + if m != nil { + return m.Asnumber + } + return "" +} + +func (m *HostMetadataV4V6Update) GetLabels() map[string]string { + if m != nil { + return m.Labels + } + return nil +} + +type HostMetadataV4V6Remove struct { + Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` + Ipv4Addr string `protobuf:"bytes,2,opt,name=ipv4_addr,json=ipv4Addr,proto3" json:"ipv4_addr,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HostMetadataV4V6Remove) Reset() { *m = HostMetadataV4V6Remove{} } +func (m *HostMetadataV4V6Remove) String() string { return proto.CompactTextString(m) } +func (*HostMetadataV4V6Remove) ProtoMessage() {} +func (*HostMetadataV4V6Remove) Descriptor() ([]byte, []int) { + return fileDescriptor_a792994fb90b9e3e, []int{41} +} +func (m *HostMetadataV4V6Remove) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HostMetadataV4V6Remove.Unmarshal(m, b) +} +func (m *HostMetadataV4V6Remove) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HostMetadataV4V6Remove.Marshal(b, m, deterministic) +} +func (m *HostMetadataV4V6Remove) XXX_Merge(src proto.Message) { + xxx_messageInfo_HostMetadataV4V6Remove.Merge(m, src) +} +func (m *HostMetadataV4V6Remove) XXX_Size() int { + return xxx_messageInfo_HostMetadataV4V6Remove.Size(m) +} +func (m *HostMetadataV4V6Remove) XXX_DiscardUnknown() { + xxx_messageInfo_HostMetadataV4V6Remove.DiscardUnknown(m) +} + +var xxx_messageInfo_HostMetadataV4V6Remove proto.InternalMessageInfo + +func (m *HostMetadataV4V6Remove) GetHostname() string { + if m != nil { + return m.Hostname + } + return "" +} + +func (m *HostMetadataV4V6Remove) GetIpv4Addr() string { + if m != nil { + return m.Ipv4Addr + } + return "" +} + type HostMetadataUpdate struct { Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` Ipv4Addr string `protobuf:"bytes,2,opt,name=ipv4_addr,json=ipv4Addr,proto3" json:"ipv4_addr,omitempty"` @@ -3094,7 +3236,7 @@ func (m *HostMetadataUpdate) Reset() { *m = HostMetadataUpdate{} } func (m *HostMetadataUpdate) String() string { return proto.CompactTextString(m) } func (*HostMetadataUpdate) ProtoMessage() {} func (*HostMetadataUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{40} + return fileDescriptor_a792994fb90b9e3e, []int{42} } func (m *HostMetadataUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HostMetadataUpdate.Unmarshal(m, b) @@ -3140,7 +3282,7 @@ func (m *HostMetadataRemove) Reset() { *m = HostMetadataRemove{} } func (m *HostMetadataRemove) String() string { return proto.CompactTextString(m) } func (*HostMetadataRemove) ProtoMessage() {} func (*HostMetadataRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{41} + return fileDescriptor_a792994fb90b9e3e, []int{43} } func (m *HostMetadataRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HostMetadataRemove.Unmarshal(m, b) @@ -3186,7 +3328,7 @@ func (m *HostMetadataV6Update) Reset() { *m = HostMetadataV6Update{} } func (m *HostMetadataV6Update) String() string { return proto.CompactTextString(m) } func (*HostMetadataV6Update) ProtoMessage() {} func (*HostMetadataV6Update) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{42} + return fileDescriptor_a792994fb90b9e3e, []int{44} } func (m *HostMetadataV6Update) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HostMetadataV6Update.Unmarshal(m, b) @@ -3232,7 +3374,7 @@ func (m *HostMetadataV6Remove) Reset() { *m = HostMetadataV6Remove{} } func (m *HostMetadataV6Remove) String() string { return proto.CompactTextString(m) } func (*HostMetadataV6Remove) ProtoMessage() {} func (*HostMetadataV6Remove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{43} + return fileDescriptor_a792994fb90b9e3e, []int{45} } func (m *HostMetadataV6Remove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_HostMetadataV6Remove.Unmarshal(m, b) @@ -3278,7 +3420,7 @@ func (m *IPAMPoolUpdate) Reset() { *m = IPAMPoolUpdate{} } func (m *IPAMPoolUpdate) String() string { return proto.CompactTextString(m) } func (*IPAMPoolUpdate) ProtoMessage() {} func (*IPAMPoolUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{44} + return fileDescriptor_a792994fb90b9e3e, []int{46} } func (m *IPAMPoolUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_IPAMPoolUpdate.Unmarshal(m, b) @@ -3323,7 +3465,7 @@ func (m *IPAMPoolRemove) Reset() { *m = IPAMPoolRemove{} } func (m *IPAMPoolRemove) String() string { return proto.CompactTextString(m) } func (*IPAMPoolRemove) ProtoMessage() {} func (*IPAMPoolRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{45} + return fileDescriptor_a792994fb90b9e3e, []int{47} } func (m *IPAMPoolRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_IPAMPoolRemove.Unmarshal(m, b) @@ -3364,7 +3506,7 @@ func (m *IPAMPool) Reset() { *m = IPAMPool{} } func (m *IPAMPool) String() string { return proto.CompactTextString(m) } func (*IPAMPool) ProtoMessage() {} func (*IPAMPool) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{46} + return fileDescriptor_a792994fb90b9e3e, []int{48} } func (m *IPAMPool) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_IPAMPool.Unmarshal(m, b) @@ -3425,7 +3567,7 @@ func (m *Encapsulation) Reset() { *m = Encapsulation{} } func (m *Encapsulation) String() string { return proto.CompactTextString(m) } func (*Encapsulation) ProtoMessage() {} func (*Encapsulation) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{47} + return fileDescriptor_a792994fb90b9e3e, []int{49} } func (m *Encapsulation) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Encapsulation.Unmarshal(m, b) @@ -3478,7 +3620,7 @@ func (m *ServiceAccountUpdate) Reset() { *m = ServiceAccountUpdate{} } func (m *ServiceAccountUpdate) String() string { return proto.CompactTextString(m) } func (*ServiceAccountUpdate) ProtoMessage() {} func (*ServiceAccountUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{48} + return fileDescriptor_a792994fb90b9e3e, []int{50} } func (m *ServiceAccountUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ServiceAccountUpdate.Unmarshal(m, b) @@ -3523,7 +3665,7 @@ func (m *ServiceAccountRemove) Reset() { *m = ServiceAccountRemove{} } func (m *ServiceAccountRemove) String() string { return proto.CompactTextString(m) } func (*ServiceAccountRemove) ProtoMessage() {} func (*ServiceAccountRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{49} + return fileDescriptor_a792994fb90b9e3e, []int{51} } func (m *ServiceAccountRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ServiceAccountRemove.Unmarshal(m, b) @@ -3562,7 +3704,7 @@ func (m *ServiceAccountID) Reset() { *m = ServiceAccountID{} } func (m *ServiceAccountID) String() string { return proto.CompactTextString(m) } func (*ServiceAccountID) ProtoMessage() {} func (*ServiceAccountID) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{50} + return fileDescriptor_a792994fb90b9e3e, []int{52} } func (m *ServiceAccountID) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ServiceAccountID.Unmarshal(m, b) @@ -3608,7 +3750,7 @@ func (m *NamespaceUpdate) Reset() { *m = NamespaceUpdate{} } func (m *NamespaceUpdate) String() string { return proto.CompactTextString(m) } func (*NamespaceUpdate) ProtoMessage() {} func (*NamespaceUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{51} + return fileDescriptor_a792994fb90b9e3e, []int{53} } func (m *NamespaceUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NamespaceUpdate.Unmarshal(m, b) @@ -3653,7 +3795,7 @@ func (m *NamespaceRemove) Reset() { *m = NamespaceRemove{} } func (m *NamespaceRemove) String() string { return proto.CompactTextString(m) } func (*NamespaceRemove) ProtoMessage() {} func (*NamespaceRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{52} + return fileDescriptor_a792994fb90b9e3e, []int{54} } func (m *NamespaceRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NamespaceRemove.Unmarshal(m, b) @@ -3691,7 +3833,7 @@ func (m *NamespaceID) Reset() { *m = NamespaceID{} } func (m *NamespaceID) String() string { return proto.CompactTextString(m) } func (*NamespaceID) ProtoMessage() {} func (*NamespaceID) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{53} + return fileDescriptor_a792994fb90b9e3e, []int{55} } func (m *NamespaceID) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_NamespaceID.Unmarshal(m, b) @@ -3731,7 +3873,7 @@ func (m *TunnelType) Reset() { *m = TunnelType{} } func (m *TunnelType) String() string { return proto.CompactTextString(m) } func (*TunnelType) ProtoMessage() {} func (*TunnelType) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{54} + return fileDescriptor_a792994fb90b9e3e, []int{56} } func (m *TunnelType) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TunnelType.Unmarshal(m, b) @@ -3796,7 +3938,7 @@ func (m *RouteUpdate) Reset() { *m = RouteUpdate{} } func (m *RouteUpdate) String() string { return proto.CompactTextString(m) } func (*RouteUpdate) ProtoMessage() {} func (*RouteUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{55} + return fileDescriptor_a792994fb90b9e3e, []int{57} } func (m *RouteUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RouteUpdate.Unmarshal(m, b) @@ -3911,7 +4053,7 @@ func (m *RouteRemove) Reset() { *m = RouteRemove{} } func (m *RouteRemove) String() string { return proto.CompactTextString(m) } func (*RouteRemove) ProtoMessage() {} func (*RouteRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{56} + return fileDescriptor_a792994fb90b9e3e, []int{58} } func (m *RouteRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_RouteRemove.Unmarshal(m, b) @@ -3955,7 +4097,7 @@ func (m *VXLANTunnelEndpointUpdate) Reset() { *m = VXLANTunnelEndpointUp func (m *VXLANTunnelEndpointUpdate) String() string { return proto.CompactTextString(m) } func (*VXLANTunnelEndpointUpdate) ProtoMessage() {} func (*VXLANTunnelEndpointUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{57} + return fileDescriptor_a792994fb90b9e3e, []int{59} } func (m *VXLANTunnelEndpointUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VXLANTunnelEndpointUpdate.Unmarshal(m, b) @@ -4035,7 +4177,7 @@ func (m *VXLANTunnelEndpointRemove) Reset() { *m = VXLANTunnelEndpointRe func (m *VXLANTunnelEndpointRemove) String() string { return proto.CompactTextString(m) } func (*VXLANTunnelEndpointRemove) ProtoMessage() {} func (*VXLANTunnelEndpointRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{58} + return fileDescriptor_a792994fb90b9e3e, []int{60} } func (m *VXLANTunnelEndpointRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_VXLANTunnelEndpointRemove.Unmarshal(m, b) @@ -4078,7 +4220,7 @@ func (m *WireguardEndpointUpdate) Reset() { *m = WireguardEndpointUpdate func (m *WireguardEndpointUpdate) String() string { return proto.CompactTextString(m) } func (*WireguardEndpointUpdate) ProtoMessage() {} func (*WireguardEndpointUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{59} + return fileDescriptor_a792994fb90b9e3e, []int{61} } func (m *WireguardEndpointUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WireguardEndpointUpdate.Unmarshal(m, b) @@ -4131,7 +4273,7 @@ func (m *WireguardEndpointRemove) Reset() { *m = WireguardEndpointRemove func (m *WireguardEndpointRemove) String() string { return proto.CompactTextString(m) } func (*WireguardEndpointRemove) ProtoMessage() {} func (*WireguardEndpointRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{60} + return fileDescriptor_a792994fb90b9e3e, []int{62} } func (m *WireguardEndpointRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WireguardEndpointRemove.Unmarshal(m, b) @@ -4174,7 +4316,7 @@ func (m *WireguardEndpointV6Update) Reset() { *m = WireguardEndpointV6Up func (m *WireguardEndpointV6Update) String() string { return proto.CompactTextString(m) } func (*WireguardEndpointV6Update) ProtoMessage() {} func (*WireguardEndpointV6Update) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{61} + return fileDescriptor_a792994fb90b9e3e, []int{63} } func (m *WireguardEndpointV6Update) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WireguardEndpointV6Update.Unmarshal(m, b) @@ -4227,7 +4369,7 @@ func (m *WireguardEndpointV6Remove) Reset() { *m = WireguardEndpointV6Re func (m *WireguardEndpointV6Remove) String() string { return proto.CompactTextString(m) } func (*WireguardEndpointV6Remove) ProtoMessage() {} func (*WireguardEndpointV6Remove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{62} + return fileDescriptor_a792994fb90b9e3e, []int{64} } func (m *WireguardEndpointV6Remove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_WireguardEndpointV6Remove.Unmarshal(m, b) @@ -4267,7 +4409,7 @@ func (m *GlobalBGPConfigUpdate) Reset() { *m = GlobalBGPConfigUpdate{} } func (m *GlobalBGPConfigUpdate) String() string { return proto.CompactTextString(m) } func (*GlobalBGPConfigUpdate) ProtoMessage() {} func (*GlobalBGPConfigUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{63} + return fileDescriptor_a792994fb90b9e3e, []int{65} } func (m *GlobalBGPConfigUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GlobalBGPConfigUpdate.Unmarshal(m, b) @@ -4324,7 +4466,7 @@ func (m *ServiceUpdate) Reset() { *m = ServiceUpdate{} } func (m *ServiceUpdate) String() string { return proto.CompactTextString(m) } func (*ServiceUpdate) ProtoMessage() {} func (*ServiceUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{64} + return fileDescriptor_a792994fb90b9e3e, []int{66} } func (m *ServiceUpdate) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ServiceUpdate.Unmarshal(m, b) @@ -4398,7 +4540,7 @@ func (m *ServiceRemove) Reset() { *m = ServiceRemove{} } func (m *ServiceRemove) String() string { return proto.CompactTextString(m) } func (*ServiceRemove) ProtoMessage() {} func (*ServiceRemove) Descriptor() ([]byte, []int) { - return fileDescriptor_a792994fb90b9e3e, []int{65} + return fileDescriptor_a792994fb90b9e3e, []int{67} } func (m *ServiceRemove) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ServiceRemove.Unmarshal(m, b) @@ -4481,6 +4623,9 @@ func init() { proto.RegisterType((*WorkloadEndpointStatusUpdate)(nil), "felix.WorkloadEndpointStatusUpdate") proto.RegisterType((*WorkloadEndpointStatusRemove)(nil), "felix.WorkloadEndpointStatusRemove") proto.RegisterType((*WireguardStatusUpdate)(nil), "felix.WireguardStatusUpdate") + proto.RegisterType((*HostMetadataV4V6Update)(nil), "felix.HostMetadataV4V6Update") + proto.RegisterMapType((map[string]string)(nil), "felix.HostMetadataV4V6Update.LabelsEntry") + proto.RegisterType((*HostMetadataV4V6Remove)(nil), "felix.HostMetadataV4V6Remove") proto.RegisterType((*HostMetadataUpdate)(nil), "felix.HostMetadataUpdate") proto.RegisterType((*HostMetadataRemove)(nil), "felix.HostMetadataRemove") proto.RegisterType((*HostMetadataV6Update)(nil), "felix.HostMetadataV6Update") @@ -4515,256 +4660,261 @@ func init() { func init() { proto.RegisterFile("felixbackend.proto", fileDescriptor_a792994fb90b9e3e) } var fileDescriptor_a792994fb90b9e3e = []byte{ - // 3971 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7b, 0x4b, 0x73, 0x1c, 0xb7, - 0x76, 0x3f, 0x67, 0x48, 0x0e, 0x67, 0xce, 0x3c, 0x38, 0x02, 0x5f, 0x43, 0x4a, 0x94, 0xe4, 0x96, - 0x5d, 0xa6, 0xfd, 0xbf, 0x96, 0xf5, 0xa7, 0xa5, 0xd1, 0x95, 0x73, 0xe3, 0x5b, 0x14, 0x49, 0x9b, - 0x63, 0x4b, 0x24, 0xab, 0x49, 0xcb, 0xb9, 0xa9, 0x5b, 0xd5, 0x69, 0x76, 0x83, 0x64, 0x47, 0x3d, - 0xdd, 0xed, 0x6e, 0x0c, 0x1f, 0x37, 0xab, 0xdc, 0xdc, 0x2c, 0x52, 0xa9, 0x54, 0x16, 0xa9, 0x4a, - 0x65, 0x95, 0x55, 0x56, 0xa9, 0x7c, 0x83, 0x2c, 0x92, 0x4d, 0xaa, 0x72, 0xbf, 0x4a, 0x76, 0x59, - 0x64, 0x9f, 0x02, 0x70, 0x80, 0x7e, 0x4c, 0x0f, 0x45, 0xe5, 0xb5, 0xe2, 0xe0, 0xe0, 0x9c, 0x1f, - 0x7e, 0x00, 0x0e, 0x80, 0x73, 0xd0, 0x20, 0x90, 0x53, 0xea, 0x7b, 0x57, 0x27, 0xb6, 0xf3, 0x96, - 0x06, 0xee, 0xe3, 0x28, 0x0e, 0x59, 0x48, 0x66, 0x85, 0xcc, 0x68, 0x43, 0xf3, 0xe8, 0x3a, 0x70, - 0x4c, 0xfa, 0xe3, 0x88, 0x26, 0xcc, 0xf8, 0xab, 0x25, 0x68, 0x1e, 0x87, 0x3b, 0x36, 0xb3, 0x23, - 0xdf, 0x0e, 0x28, 0xf9, 0x18, 0xe6, 0x13, 0x5e, 0x15, 0x38, 0xd4, 0x0a, 0x46, 0xc3, 0x13, 0x1a, - 0xf7, 0xe6, 0x1f, 0x56, 0x36, 0x66, 0xcc, 0x8e, 0x12, 0xef, 0x0b, 0x29, 0xd9, 0x80, 0x39, 0x2f, - 0xb0, 0x92, 0xeb, 0xc0, 0xe9, 0x55, 0x1e, 0x56, 0x36, 0x9a, 0x9b, 0xed, 0xc7, 0xa2, 0x81, 0xc7, - 0x83, 0x80, 0xe3, 0xef, 0x4d, 0x99, 0x35, 0x4f, 0xfc, 0x22, 0xcf, 0xa1, 0xe5, 0x45, 0x09, 0x65, - 0xd6, 0x28, 0x72, 0x6d, 0x46, 0x7b, 0x55, 0xa1, 0x4e, 0x94, 0xfa, 0xe1, 0x11, 0x65, 0xdf, 0x8b, - 0x9a, 0xbd, 0x29, 0xb3, 0x29, 0x34, 0x65, 0x91, 0x7c, 0x03, 0x44, 0x1a, 0xba, 0xd4, 0x67, 0xb6, - 0x32, 0x9f, 0x16, 0xe6, 0x2b, 0x59, 0xf3, 0x1d, 0x5e, 0xaf, 0x31, 0xba, 0xc2, 0x28, 0x23, 0x4b, - 0x19, 0xc4, 0x74, 0x18, 0x5e, 0xd0, 0xde, 0xcc, 0x38, 0x03, 0x53, 0xd4, 0x68, 0x06, 0xb2, 0x48, - 0x0e, 0x61, 0xc9, 0x76, 0x98, 0x77, 0x41, 0xad, 0x28, 0x0e, 0x4f, 0x3d, 0x9f, 0x2a, 0x12, 0xb3, - 0x02, 0x61, 0x0d, 0x11, 0xb6, 0x84, 0xce, 0xa1, 0x54, 0xd1, 0x3c, 0x16, 0xec, 0x71, 0x71, 0x09, - 0x22, 0x72, 0xaa, 0x4d, 0x46, 0xd4, 0xdc, 0xf2, 0x88, 0xc8, 0xf1, 0x35, 0x2c, 0x2a, 0xc4, 0xd0, - 0xf7, 0x9c, 0x6b, 0x45, 0x71, 0x4e, 0x00, 0xae, 0xe6, 0x01, 0x85, 0x86, 0x66, 0x48, 0xec, 0x31, - 0xe9, 0x38, 0x1c, 0xf2, 0xab, 0x4f, 0x84, 0xd3, 0xf4, 0x72, 0x70, 0x29, 0xbb, 0xf3, 0x30, 0x61, - 0x16, 0x0d, 0xdc, 0x28, 0xf4, 0x02, 0xed, 0x04, 0x8d, 0x1c, 0xdc, 0x5e, 0x98, 0xb0, 0x5d, 0xd4, - 0x48, 0xd9, 0x9d, 0x8f, 0x49, 0xc7, 0xe1, 0x90, 0x1d, 0x4c, 0x84, 0x4b, 0xd9, 0x9d, 0x8f, 0x49, - 0xc9, 0x2f, 0xa0, 0x77, 0x19, 0xc6, 0x6f, 0xfd, 0xd0, 0x76, 0xc7, 0x18, 0x36, 0x05, 0xe4, 0x3a, - 0x42, 0xfe, 0x80, 0x6a, 0x63, 0x2c, 0x97, 0x2f, 0x4b, 0x6b, 0xca, 0xa1, 0x91, 0x6d, 0xeb, 0x46, - 0x68, 0xcd, 0x78, 0x0c, 0x1a, 0x59, 0x7f, 0x09, 0x6d, 0x27, 0x0c, 0x4e, 0xbd, 0x33, 0x45, 0xb5, - 0x2d, 0xf0, 0x16, 0x10, 0x6f, 0x5b, 0xd4, 0x69, 0x82, 0x2d, 0x27, 0x53, 0xd6, 0x03, 0x38, 0xa4, - 0xcc, 0x76, 0xed, 0x74, 0x55, 0x75, 0xc6, 0x06, 0xf0, 0x35, 0x6a, 0xe4, 0xe7, 0x23, 0x2f, 0x1d, - 0x87, 0xc3, 0x1e, 0x92, 0x89, 0x70, 0xf9, 0xf9, 0xc8, 0x4b, 0xc9, 0x16, 0x74, 0xbd, 0xc8, 0x1e, - 0x5a, 0x51, 0x18, 0xfa, 0x8a, 0x59, 0x57, 0x40, 0x2d, 0xe9, 0xc5, 0xba, 0xf5, 0xfa, 0x30, 0x0c, - 0x7d, 0xcd, 0xaa, 0xc3, 0x0d, 0x52, 0x49, 0x1e, 0x02, 0xd9, 0xdc, 0x29, 0x85, 0xd0, 0x4c, 0x34, - 0x04, 0xb2, 0x38, 0x82, 0xe5, 0x84, 0xc6, 0x17, 0x9e, 0x43, 0x2d, 0xdb, 0x71, 0xc2, 0x51, 0xea, - 0x13, 0x0b, 0x02, 0xe8, 0x2e, 0x02, 0x1d, 0x49, 0xa5, 0x2d, 0xa9, 0xa3, 0x19, 0x2d, 0x26, 0x25, - 0xf2, 0x32, 0x50, 0x64, 0xb7, 0x78, 0x03, 0xa8, 0xe6, 0x58, 0x00, 0x45, 0xa6, 0xdb, 0xd0, 0x0d, - 0xec, 0x21, 0x4d, 0x22, 0xdb, 0xd1, 0x5b, 0xd3, 0x92, 0x80, 0x5b, 0x46, 0xb8, 0x7d, 0x55, 0xad, - 0xe9, 0xcd, 0x07, 0x79, 0x51, 0x1e, 0x04, 0x39, 0x2d, 0x97, 0x83, 0x68, 0x3a, 0x29, 0x08, 0x32, - 0x79, 0x0e, 0xad, 0x38, 0x1c, 0x31, 0xcd, 0x62, 0x25, 0xb7, 0xc5, 0x9a, 0xbc, 0x2a, 0xdd, 0xe4, - 0xe3, 0xb4, 0x98, 0x1a, 0x62, 0xcb, 0xbd, 0x71, 0xc3, 0x74, 0x6f, 0x8e, 0xd3, 0x22, 0xd9, 0x86, - 0xe6, 0x05, 0xa3, 0x91, 0x6a, 0x70, 0x55, 0xd8, 0x3d, 0x44, 0xbb, 0x37, 0xbf, 0xf7, 0x6a, 0x6b, - 0xff, 0x78, 0x14, 0x04, 0xd4, 0x1f, 0x5b, 0xb1, 0xc0, 0xcd, 0x74, 0xdf, 0x25, 0x08, 0x36, 0xbe, - 0xf6, 0x2e, 0x10, 0x4d, 0x45, 0x80, 0x20, 0x93, 0x5f, 0xc2, 0xea, 0xa5, 0x17, 0xd3, 0xb3, 0x91, - 0x1d, 0x8f, 0x6f, 0x23, 0x77, 0x05, 0xe4, 0x7d, 0xb5, 0xd6, 0x95, 0xde, 0x18, 0xab, 0x95, 0xcb, - 0xf2, 0xaa, 0x09, 0xe8, 0x48, 0xf8, 0xde, 0xcd, 0xe8, 0x9a, 0xee, 0x38, 0x3a, 0x72, 0xff, 0x01, - 0x7a, 0x67, 0x7e, 0x78, 0x62, 0xfb, 0xd6, 0xc9, 0x59, 0x64, 0xe5, 0xb7, 0x95, 0x75, 0x01, 0x7e, - 0x0f, 0xc1, 0xbf, 0x11, 0x6a, 0x2f, 0xbf, 0x39, 0x2c, 0xec, 0x2f, 0x4b, 0xd2, 0xfe, 0xe5, 0x59, - 0x94, 0xad, 0x20, 0x3f, 0x83, 0x36, 0x0d, 0x1c, 0x3b, 0x4a, 0x46, 0xbe, 0xcd, 0xbc, 0x30, 0xe8, - 0xdd, 0x17, 0x68, 0x8b, 0x88, 0xb6, 0x9b, 0xad, 0xdb, 0x9b, 0x32, 0xf3, 0xca, 0xe4, 0x77, 0xa1, - 0xa3, 0x56, 0x0b, 0x92, 0x79, 0x90, 0x33, 0xc7, 0x55, 0xa2, 0x49, 0xb4, 0x93, 0xac, 0x20, 0x6b, - 0x8e, 0x03, 0xf5, 0xb0, 0xcc, 0x5c, 0x0f, 0x8f, 0x32, 0xc7, 0x41, 0x71, 0xe0, 0x5e, 0xc9, 0x90, - 0x5f, 0xf4, 0x15, 0x97, 0x0f, 0x72, 0x6e, 0x32, 0x36, 0xea, 0x6f, 0xfa, 0x9a, 0xd7, 0xea, 0xe5, - 0xa4, 0xca, 0xc9, 0x8d, 0x20, 0x63, 0xe3, 0x5d, 0x8d, 0x68, 0xf6, 0x65, 0x8d, 0x60, 0x4f, 0x8e, - 0x61, 0x25, 0xbf, 0x3f, 0xa7, 0x9d, 0x78, 0x94, 0xdb, 0x76, 0xb2, 0x5b, 0x74, 0x86, 0xff, 0xe2, - 0x79, 0x89, 0xbc, 0x14, 0x15, 0x59, 0x7f, 0x78, 0x03, 0x6a, 0xba, 0x99, 0x9d, 0x97, 0xc8, 0x5f, - 0x36, 0x60, 0x2e, 0xb2, 0xaf, 0xf9, 0x79, 0x67, 0xfc, 0xc5, 0x2c, 0xb4, 0xbf, 0x8e, 0xc3, 0xe1, - 0x8d, 0x71, 0x69, 0xbd, 0x34, 0x2e, 0x3d, 0x84, 0xa5, 0x28, 0x0e, 0x1d, 0x9a, 0x24, 0x56, 0xc2, - 0x6c, 0x36, 0x4a, 0xf2, 0x71, 0xa3, 0x0a, 0xb0, 0x0e, 0xa5, 0xce, 0x91, 0x50, 0x49, 0x43, 0xb6, - 0x68, 0x5c, 0x4c, 0xfe, 0x00, 0xee, 0xe6, 0x63, 0x8e, 0x3c, 0xae, 0x0c, 0x26, 0x1f, 0x94, 0x84, - 0x1e, 0x05, 0xf0, 0xde, 0xf9, 0x84, 0xba, 0x89, 0x2d, 0xe0, 0x98, 0xce, 0xbe, 0xa3, 0x05, 0x3d, - 0xae, 0x25, 0x2d, 0xa0, 0x1f, 0xf8, 0xf0, 0x60, 0x3c, 0x1a, 0xc9, 0xf7, 0x43, 0x06, 0xa0, 0x8f, - 0x26, 0x04, 0x25, 0x85, 0xbe, 0xdc, 0xbb, 0xbc, 0xa1, 0xfe, 0xc6, 0xd6, 0xb0, 0x4f, 0x73, 0xb7, - 0x68, 0x4d, 0xf7, 0x6b, 0x42, 0x6b, 0xd8, 0xb7, 0x37, 0x90, 0xee, 0x6e, 0x85, 0x3e, 0x35, 0x72, - 0x3b, 0x98, 0x5e, 0x43, 0x85, 0xce, 0x2c, 0x5d, 0x96, 0x55, 0x64, 0xfd, 0xf1, 0xd7, 0x15, 0x68, - 0xe5, 0x76, 0xb7, 0xe7, 0x50, 0x93, 0x7b, 0x65, 0xaf, 0xf2, 0x70, 0x3a, 0x33, 0x39, 0x59, 0x25, - 0x2c, 0xec, 0x06, 0x2c, 0xbe, 0x36, 0x51, 0x7d, 0xed, 0x05, 0x34, 0x33, 0x62, 0xd2, 0x85, 0xe9, - 0xb7, 0xf4, 0x5a, 0x64, 0x50, 0x0d, 0x93, 0xff, 0x24, 0x8b, 0x30, 0x7b, 0x61, 0xfb, 0x23, 0x99, - 0x26, 0x35, 0x4c, 0x59, 0xf8, 0xb2, 0xfa, 0xd3, 0x8a, 0x51, 0x87, 0x9a, 0xcc, 0xad, 0x8c, 0xbf, - 0xa9, 0x40, 0x33, 0x93, 0x37, 0x91, 0x0e, 0x54, 0x3d, 0x17, 0x41, 0xaa, 0x9e, 0x4b, 0x7a, 0x30, - 0x37, 0xa4, 0x7c, 0x35, 0x24, 0xbd, 0xea, 0xc3, 0xe9, 0x8d, 0x86, 0xa9, 0x8a, 0xe4, 0x09, 0xcc, - 0xb0, 0xeb, 0x48, 0x2e, 0x86, 0x8e, 0x1e, 0x98, 0x0c, 0x96, 0xfc, 0x7d, 0x7c, 0x1d, 0x51, 0x53, - 0x68, 0x1a, 0x9f, 0x41, 0x43, 0x8b, 0x48, 0x0d, 0xaa, 0x83, 0xc3, 0xee, 0x14, 0x99, 0xe7, 0xed, - 0x5b, 0x5b, 0xfb, 0x3b, 0xd6, 0xe1, 0x81, 0x79, 0xdc, 0xad, 0x90, 0x39, 0x98, 0xde, 0xdf, 0x3d, - 0xee, 0x56, 0x8d, 0x08, 0xba, 0xc5, 0x94, 0x6c, 0x8c, 0xde, 0x23, 0x68, 0xdb, 0xae, 0x4b, 0x5d, - 0x2b, 0x4f, 0xb2, 0x25, 0x84, 0xaf, 0x91, 0xe9, 0xc7, 0x30, 0x2f, 0x5d, 0x25, 0x55, 0x9b, 0x16, - 0x6a, 0x1d, 0x14, 0xa3, 0xa2, 0xb1, 0x8e, 0x63, 0x81, 0xde, 0x50, 0x68, 0xcc, 0xb0, 0x61, 0xa1, - 0x24, 0x3d, 0x23, 0x0f, 0xb5, 0x5a, 0x73, 0xb3, 0x9b, 0xee, 0x09, 0x5c, 0x63, 0xb0, 0x23, 0x58, - 0x6e, 0xc0, 0x1c, 0xa6, 0x68, 0x98, 0xb1, 0x76, 0xf2, 0x6a, 0xa6, 0xaa, 0x36, 0x9e, 0x17, 0x9a, - 0x40, 0x26, 0xef, 0x6c, 0xc2, 0x78, 0x00, 0x0d, 0x2d, 0x20, 0x04, 0x66, 0x78, 0x50, 0x85, 0xd4, - 0xc5, 0x6f, 0x23, 0x84, 0x39, 0x54, 0x20, 0x4f, 0xa0, 0xed, 0x05, 0x27, 0xe1, 0x28, 0x70, 0xad, - 0x78, 0xe4, 0xd3, 0x04, 0x1d, 0xaf, 0xa9, 0x02, 0xa5, 0x91, 0x4f, 0xcd, 0x16, 0x6a, 0xf0, 0x42, - 0x42, 0x36, 0xa1, 0x13, 0x8e, 0x58, 0xd6, 0xa4, 0x3a, 0x6e, 0xd2, 0x56, 0x2a, 0xc2, 0xc6, 0xf8, - 0x25, 0x90, 0xf1, 0x4c, 0x91, 0x3c, 0xc8, 0xf4, 0x64, 0x5e, 0xf5, 0x44, 0x28, 0xe0, 0x58, 0x7d, - 0x04, 0x35, 0x99, 0x2d, 0xe2, 0x50, 0xb5, 0x73, 0x4a, 0x26, 0x56, 0x1a, 0xcf, 0xf2, 0xe8, 0x38, - 0x4e, 0xef, 0x42, 0x37, 0x36, 0xa1, 0xae, 0xca, 0x7c, 0x94, 0x98, 0x47, 0x63, 0x35, 0x4a, 0xfc, - 0xb7, 0x1e, 0xb9, 0x6a, 0x66, 0xe4, 0xfe, 0xa5, 0x02, 0x35, 0x69, 0x44, 0xee, 0x41, 0x43, 0x47, - 0xab, 0x62, 0x2f, 0x6d, 0x98, 0xa9, 0xe0, 0xff, 0x66, 0x5c, 0x39, 0x87, 0x51, 0xc0, 0x62, 0xdb, - 0x79, 0x4b, 0x5d, 0xb1, 0xf8, 0xea, 0x66, 0x2a, 0x20, 0xab, 0x50, 0x8f, 0x62, 0x6a, 0xb9, 0x81, - 0xcd, 0xc4, 0x71, 0x52, 0xe7, 0xbe, 0x45, 0x77, 0x02, 0x9b, 0x19, 0x7f, 0xdf, 0x85, 0x19, 0x0e, - 0x41, 0x96, 0xa1, 0xc6, 0xd3, 0xeb, 0x30, 0xc0, 0xae, 0x63, 0x89, 0x7c, 0x0e, 0xe0, 0x45, 0xd6, - 0x05, 0x8d, 0x13, 0x5e, 0x57, 0x15, 0xeb, 0xba, 0xab, 0xd7, 0xf5, 0x1b, 0x29, 0x37, 0x1b, 0x5e, - 0x84, 0x3f, 0xc9, 0xff, 0xe3, 0x8d, 0x85, 0x2c, 0x74, 0x42, 0x1f, 0xcf, 0xc4, 0xf9, 0xd4, 0x39, - 0x85, 0xd8, 0xd4, 0x0a, 0x64, 0x05, 0xe6, 0x92, 0xd8, 0xb1, 0x02, 0xca, 0x89, 0xf1, 0xd5, 0x57, - 0x4b, 0x62, 0x67, 0x9f, 0x32, 0xf2, 0x19, 0x34, 0x78, 0x45, 0x14, 0xc6, 0x2c, 0xe9, 0xcd, 0x8a, - 0xfe, 0x6b, 0x1f, 0x0f, 0x63, 0x66, 0xda, 0xc1, 0x19, 0x35, 0xeb, 0x49, 0xec, 0xf0, 0x52, 0x42, - 0x9e, 0xc3, 0xaa, 0xc0, 0xb1, 0x87, 0xd4, 0x15, 0x46, 0x96, 0x17, 0x59, 0x09, 0x65, 0x96, 0xe7, - 0x26, 0xbd, 0x96, 0x40, 0x5e, 0xe4, 0xc8, 0xbc, 0x9e, 0x5b, 0x0c, 0xa2, 0x23, 0xca, 0x06, 0x6e, - 0xc2, 0x09, 0xb8, 0x09, 0x13, 0x04, 0x6a, 0x92, 0x80, 0x9b, 0x30, 0x24, 0xc0, 0x2b, 0x24, 0x81, - 0xb9, 0x49, 0x04, 0xdc, 0x84, 0x69, 0x02, 0x02, 0xa7, 0x94, 0x40, 0x5b, 0x12, 0xe0, 0xc8, 0x63, - 0x04, 0xd6, 0xa1, 0xe1, 0x39, 0xc3, 0xc8, 0x12, 0xdb, 0x26, 0x0f, 0x39, 0x66, 0xf7, 0xa6, 0xcc, - 0x3a, 0x17, 0x89, 0x1d, 0xf1, 0x2b, 0xe8, 0xe8, 0x6a, 0xcb, 0x09, 0x5d, 0x75, 0xe6, 0xa8, 0xd4, - 0x69, 0x80, 0x8a, 0x5b, 0x81, 0xbb, 0x1d, 0xba, 0x22, 0x1f, 0x57, 0xb6, 0xbc, 0x4c, 0x1e, 0x41, - 0x87, 0x0f, 0x4c, 0x86, 0x0c, 0x08, 0x32, 0xcd, 0x24, 0x76, 0x34, 0x87, 0x47, 0xd0, 0xe1, 0xe4, - 0x33, 0x4a, 0x4d, 0xa9, 0xe4, 0x26, 0x29, 0xd1, 0x9f, 0xc0, 0x02, 0x2a, 0x89, 0xee, 0x29, 0xcd, - 0x79, 0xa1, 0x39, 0x2f, 0x34, 0x79, 0xc7, 0x50, 0x7b, 0x13, 0x5a, 0x41, 0xc8, 0x2c, 0xed, 0x09, - 0xa7, 0xe5, 0x9e, 0xd0, 0x0c, 0x42, 0xa6, 0x0a, 0xe4, 0x3e, 0xf0, 0xa2, 0xa5, 0x1c, 0xe2, 0x4c, - 0x20, 0x37, 0x82, 0x90, 0x1d, 0x49, 0x9f, 0x78, 0x0a, 0x6d, 0x55, 0x2f, 0xa7, 0xe5, 0x7c, 0xc2, - 0xb4, 0x34, 0xa5, 0x8d, 0x9c, 0x19, 0x44, 0x55, 0xb3, 0xec, 0x69, 0xd4, 0x1d, 0x39, 0xd1, 0x88, - 0x9a, 0x4e, 0xf6, 0x1f, 0xde, 0x80, 0xba, 0xa3, 0xe6, 0xfb, 0x43, 0x69, 0x95, 0x4e, 0xdd, 0x5b, - 0x31, 0x75, 0x15, 0xa1, 0xa5, 0x26, 0x85, 0xec, 0x02, 0xc9, 0x69, 0xc9, 0x19, 0xf4, 0x6f, 0x9c, - 0xc1, 0x8a, 0x39, 0x9f, 0x81, 0x10, 0x93, 0xf8, 0xa9, 0x84, 0x29, 0x4c, 0xe4, 0x50, 0x1e, 0x57, - 0xb2, 0xaf, 0x7a, 0x9a, 0x50, 0xb7, 0x30, 0x9f, 0x81, 0xd6, 0xdd, 0xc9, 0x4c, 0xe9, 0x57, 0xb0, - 0xae, 0x07, 0xbc, 0xd4, 0x71, 0x23, 0x61, 0xb6, 0x82, 0x53, 0x30, 0xe6, 0xbb, 0x68, 0x3f, 0xd9, - 0xf1, 0x7f, 0xd4, 0xf6, 0x3b, 0x65, 0xbe, 0xbf, 0x09, 0x4b, 0x61, 0xec, 0x9d, 0x79, 0x81, 0xed, - 0x0b, 0x12, 0x09, 0xf5, 0xa9, 0xc3, 0xc2, 0xb8, 0x17, 0x8b, 0x2d, 0x68, 0x41, 0x55, 0x1e, 0xc5, - 0xce, 0x11, 0x56, 0xe5, 0x6c, 0x78, 0xc3, 0xda, 0x26, 0xc9, 0xdb, 0xec, 0x24, 0x4c, 0xdb, 0xec, - 0xc2, 0x83, 0x5c, 0x3b, 0xe9, 0x75, 0x84, 0xb6, 0x66, 0xc2, 0xfa, 0x5e, 0xa6, 0x45, 0x7d, 0x29, - 0x51, 0x0a, 0xa3, 0xfa, 0x5c, 0x80, 0x19, 0xe5, 0x61, 0xb0, 0xd7, 0x79, 0x98, 0x17, 0xb0, 0xaa, - 0x61, 0xd4, 0xf0, 0x6b, 0x80, 0x0b, 0x01, 0xb0, 0xac, 0x14, 0xf6, 0xc5, 0xc8, 0x4f, 0x34, 0xcd, - 0x0d, 0xc0, 0xe5, 0x98, 0x69, 0x76, 0x0c, 0xfe, 0x3f, 0x2c, 0x16, 0xc6, 0x5a, 0x64, 0xa4, 0xbd, - 0xdf, 0xc8, 0xed, 0x9e, 0xe4, 0xc6, 0x5a, 0x54, 0x91, 0x1d, 0xb8, 0x5f, 0x66, 0x92, 0xf6, 0xbb, - 0xf7, 0xa7, 0xd2, 0xf8, 0xee, 0xb8, 0xb1, 0xee, 0x76, 0xae, 0x61, 0xc9, 0x57, 0x36, 0xfc, 0xeb, - 0x42, 0xc3, 0x82, 0xec, 0x78, 0xc3, 0x19, 0x93, 0x4c, 0xc3, 0x7f, 0x52, 0x68, 0x38, 0x35, 0x4e, - 0x1b, 0xfe, 0x5e, 0x9e, 0x09, 0xc5, 0x5b, 0xb1, 0xa1, 0xcd, 0x9c, 0xf3, 0xde, 0x55, 0x2e, 0x5b, - 0xcb, 0x5f, 0x8a, 0xbd, 0xe6, 0x1a, 0xe6, 0x72, 0xa2, 0x3b, 0x93, 0x95, 0x73, 0xd8, 0x2c, 0xa7, - 0x3c, 0xec, 0xf5, 0xbb, 0x61, 0x5d, 0x4d, 0x35, 0x07, 0xfb, 0x39, 0xc0, 0x39, 0x63, 0x11, 0xe2, - 0xfc, 0x2a, 0x17, 0xd5, 0xed, 0x1d, 0x1f, 0x1f, 0x4a, 0xeb, 0x06, 0xd7, 0x51, 0x06, 0x75, 0x95, - 0x1f, 0xf7, 0xfe, 0x28, 0x77, 0x41, 0xcb, 0xcf, 0x73, 0x7d, 0xf1, 0xa9, 0x95, 0x78, 0xd4, 0xce, - 0xc3, 0x09, 0xcb, 0x73, 0x7b, 0xbf, 0xc5, 0x33, 0x9e, 0x97, 0x07, 0xee, 0xcb, 0x1a, 0xcc, 0xf0, - 0x2d, 0xea, 0x25, 0x40, 0x5d, 0x6d, 0x57, 0xdf, 0xd6, 0xea, 0xff, 0x5a, 0xe9, 0xfe, 0xb6, 0x62, - 0x82, 0x1f, 0x9e, 0x59, 0x51, 0x4c, 0x4f, 0xbd, 0x2b, 0xe3, 0x1b, 0x58, 0x28, 0xa3, 0xbe, 0x06, - 0x75, 0xed, 0x84, 0x12, 0x58, 0x97, 0x79, 0xba, 0x21, 0x66, 0x0d, 0x63, 0x70, 0x59, 0x30, 0xfe, - 0xae, 0x02, 0x0d, 0xdd, 0x29, 0x99, 0x4e, 0xb0, 0xf3, 0xd0, 0x95, 0xc1, 0x91, 0x48, 0x27, 0x44, - 0x91, 0x3c, 0x81, 0xd9, 0xc8, 0x66, 0xe7, 0x2a, 0x02, 0x5a, 0x2b, 0x8e, 0xc7, 0xe3, 0x43, 0x9b, - 0x9d, 0xcb, 0x91, 0x91, 0x8a, 0x6b, 0xdf, 0x41, 0x43, 0xcb, 0xc8, 0x32, 0xcc, 0xd2, 0x2b, 0xdb, - 0x61, 0x92, 0xd5, 0xde, 0x94, 0x29, 0x8b, 0xa4, 0x07, 0x35, 0xd9, 0x23, 0x19, 0xd2, 0xed, 0x4d, - 0x99, 0x58, 0x7e, 0xd9, 0x02, 0xe0, 0x38, 0x72, 0x16, 0x8c, 0xbf, 0xae, 0x40, 0x2b, 0x3b, 0x98, - 0xe4, 0x6b, 0x68, 0xda, 0x41, 0x10, 0x32, 0x71, 0x89, 0xa4, 0x42, 0xb9, 0x0f, 0x4b, 0x86, 0xfd, - 0xf1, 0x56, 0xaa, 0x26, 0x13, 0xb4, 0xac, 0xe1, 0xda, 0x57, 0xd0, 0x2d, 0x2a, 0xbc, 0x57, 0xaa, - 0xf6, 0x02, 0xe6, 0x0b, 0xc7, 0x86, 0x08, 0x5c, 0xf9, 0x39, 0xc4, 0xed, 0x67, 0x65, 0x6e, 0xc5, - 0x65, 0xe2, 0xc0, 0xa9, 0x4a, 0x19, 0xff, 0x6d, 0xbc, 0x82, 0xba, 0x3e, 0x70, 0x7b, 0x50, 0xc3, - 0xbb, 0x8e, 0x0a, 0x06, 0x1e, 0x58, 0x26, 0x8b, 0xd9, 0x90, 0x77, 0x6f, 0x4a, 0x06, 0xbd, 0x2f, - 0xbb, 0xd0, 0x91, 0xf5, 0x56, 0x18, 0x8b, 0xc5, 0x68, 0x3c, 0x83, 0x86, 0x3e, 0x20, 0x39, 0xdf, - 0x53, 0x2f, 0x4e, 0x18, 0x72, 0x90, 0x05, 0x4e, 0xc2, 0xb7, 0x13, 0xa6, 0x48, 0xf0, 0xdf, 0xc6, - 0x5f, 0x56, 0x80, 0x14, 0x73, 0xf2, 0xc1, 0x0e, 0xcf, 0xc9, 0xc2, 0xd8, 0x39, 0xa7, 0x09, 0x8b, - 0x6d, 0x16, 0xc6, 0xdc, 0x53, 0x65, 0xd7, 0x3b, 0x59, 0xf1, 0xc0, 0x25, 0x0f, 0xa0, 0xa9, 0x2f, - 0x00, 0x3c, 0x19, 0xf0, 0x36, 0x4c, 0x50, 0x22, 0xa9, 0xa0, 0x2f, 0x06, 0x3c, 0x57, 0x04, 0xbd, - 0x0d, 0x13, 0x94, 0x68, 0xe0, 0x7e, 0x3b, 0x53, 0xaf, 0x74, 0xab, 0x66, 0xfd, 0x3c, 0x4c, 0x98, - 0xe8, 0xc8, 0x15, 0x2c, 0x97, 0x7f, 0x82, 0x21, 0x9f, 0x64, 0xd2, 0x87, 0xd5, 0x09, 0xf7, 0x09, - 0x98, 0xa6, 0x7c, 0x01, 0x75, 0xd5, 0x04, 0x5e, 0xaa, 0xac, 0x4c, 0xfa, 0x06, 0xa3, 0x15, 0x8d, - 0xff, 0x98, 0x86, 0x6e, 0xb1, 0x9a, 0x0f, 0x65, 0xc2, 0x6c, 0xa6, 0xb2, 0x35, 0x59, 0x28, 0x4b, - 0x44, 0xb8, 0xdb, 0x0c, 0x6d, 0x07, 0x87, 0x80, 0xff, 0xe4, 0x7d, 0x57, 0xdf, 0xfe, 0xf8, 0x19, - 0x2c, 0xe3, 0x6a, 0x40, 0x11, 0x3f, 0x76, 0xef, 0x42, 0xc3, 0x8b, 0x2e, 0x9e, 0xf2, 0x70, 0x48, - 0xc6, 0xd6, 0x0d, 0xb3, 0xce, 0x05, 0xfb, 0x94, 0xa9, 0xca, 0xbe, 0xac, 0xac, 0xe9, 0xca, 0xbe, - 0xa8, 0xfc, 0x08, 0x66, 0x79, 0x46, 0xa4, 0x02, 0x62, 0x15, 0xce, 0x1d, 0x7b, 0x34, 0x1e, 0x04, - 0xa7, 0xa1, 0x29, 0x6b, 0xc9, 0x27, 0x50, 0x97, 0x0d, 0xd8, 0xac, 0x57, 0x17, 0x9a, 0x1d, 0x7d, - 0xd3, 0xcf, 0x84, 0xe2, 0x9c, 0x68, 0xcf, 0x66, 0xa8, 0xda, 0x17, 0xaa, 0x8d, 0x89, 0xaa, 0x7d, - 0xae, 0xba, 0x05, 0xeb, 0xb6, 0xef, 0x87, 0x97, 0x56, 0x12, 0x85, 0xe1, 0x29, 0x75, 0xad, 0x24, - 0x1c, 0xc5, 0x0e, 0xc5, 0xcd, 0x89, 0xaa, 0xc8, 0x76, 0x4d, 0x28, 0x1d, 0x49, 0x9d, 0x23, 0xa1, - 0x72, 0x88, 0x1a, 0xe4, 0xdb, 0xfc, 0xfa, 0x6d, 0x8a, 0x06, 0x37, 0x26, 0xcc, 0xd1, 0xff, 0xf2, - 0x1a, 0xde, 0x1e, 0xf7, 0x38, 0x4c, 0x58, 0x6f, 0xef, 0x71, 0xc6, 0x16, 0x74, 0xb2, 0xf7, 0x75, - 0x83, 0x9d, 0xa2, 0xe7, 0x57, 0xdf, 0xe9, 0xf9, 0x3e, 0x90, 0xf1, 0xcf, 0xa3, 0xe4, 0xa3, 0x0c, - 0x87, 0xa5, 0x92, 0x9b, 0x41, 0xf4, 0xf8, 0xcf, 0x33, 0x1e, 0x3f, 0x9d, 0x3b, 0x84, 0x72, 0xdf, - 0x48, 0x53, 0x6f, 0xff, 0xf7, 0x2a, 0xb4, 0xb2, 0x55, 0x65, 0xd7, 0x12, 0x45, 0x0f, 0xae, 0x8e, - 0x79, 0xb0, 0xf6, 0xc3, 0xe9, 0x1b, 0xfd, 0xf0, 0xa7, 0x30, 0xaf, 0x93, 0x60, 0x4b, 0x1a, 0xd4, - 0xca, 0x0d, 0x3a, 0x5a, 0xef, 0x58, 0x58, 0x3e, 0x83, 0x8e, 0xca, 0x98, 0xad, 0x1b, 0x3d, 0xbe, - 0x85, 0x89, 0xb4, 0x34, 0x7b, 0x0a, 0xed, 0xd3, 0x30, 0xbe, 0xb4, 0x63, 0xd5, 0x5c, 0x7d, 0x82, - 0x15, 0x6a, 0x49, 0xab, 0xc7, 0xb0, 0x40, 0xaf, 0x22, 0xea, 0x30, 0xea, 0x5a, 0x62, 0xdd, 0xd8, - 0xae, 0x1b, 0xab, 0x85, 0x7b, 0x47, 0x55, 0x0d, 0xa2, 0x8b, 0xa7, 0x5b, 0xbc, 0xa2, 0xa8, 0xdf, - 0x47, 0xfd, 0xd9, 0x31, 0xfd, 0xbe, 0xd0, 0x37, 0x7e, 0x27, 0x3f, 0xc3, 0xe8, 0x65, 0xb7, 0x9b, - 0x61, 0x23, 0x86, 0xba, 0xa2, 0x5d, 0x3a, 0x57, 0x9f, 0x40, 0xd7, 0x0b, 0xce, 0x62, 0x9a, 0x24, - 0xf2, 0x83, 0xbe, 0xa7, 0xcf, 0xfa, 0x79, 0x94, 0x1f, 0xa2, 0x98, 0x6f, 0xef, 0xb4, 0xa0, 0x89, - 0x57, 0x6e, 0x34, 0xa7, 0x68, 0x3c, 0x87, 0x39, 0x5c, 0xfd, 0x64, 0x09, 0x6a, 0xf4, 0x8a, 0xe7, - 0x14, 0x6a, 0x27, 0xa4, 0x57, 0x6c, 0x10, 0x71, 0xb1, 0x70, 0xf0, 0x48, 0xad, 0x2b, 0x4e, 0x38, - 0x32, 0x4c, 0x58, 0x28, 0xb9, 0x78, 0x27, 0x8f, 0xa0, 0xed, 0x25, 0xa1, 0xc5, 0xbc, 0x21, 0x4d, - 0x98, 0x3d, 0x54, 0x58, 0x2d, 0x2f, 0x09, 0x8f, 0x95, 0x8c, 0x2c, 0x43, 0x6d, 0x14, 0x71, 0x15, - 0x01, 0x59, 0x31, 0xb1, 0x64, 0x44, 0xd0, 0x9b, 0x74, 0xe9, 0x7e, 0xdb, 0x55, 0xf2, 0x19, 0xd4, - 0xe4, 0xbd, 0x31, 0x5e, 0x5f, 0x2d, 0xe9, 0x8f, 0x54, 0xb9, 0xeb, 0x66, 0x54, 0x32, 0x36, 0xa0, - 0x93, 0xaf, 0xe1, 0xdc, 0x10, 0x00, 0x03, 0x37, 0xd4, 0xdc, 0x2a, 0xe3, 0xf6, 0x7e, 0xf3, 0x7b, - 0x05, 0xf7, 0x6e, 0xba, 0x8b, 0x7f, 0x9f, 0xe3, 0xef, 0x3d, 0xbb, 0x39, 0x98, 0xd4, 0xf2, 0xfb, - 0x6f, 0x83, 0x67, 0xb0, 0x54, 0x7a, 0xf9, 0x4e, 0xd6, 0x01, 0xa2, 0xd1, 0x89, 0xef, 0x39, 0x56, - 0xba, 0x2f, 0x37, 0xa4, 0xe4, 0x3b, 0x7a, 0xfd, 0xde, 0x97, 0x5b, 0xc6, 0x6b, 0xb9, 0x94, 0x0a, - 0xaf, 0x14, 0xd6, 0x40, 0x6f, 0xa7, 0x2a, 0x00, 0x56, 0x65, 0x7d, 0xd8, 0xf2, 0x35, 0x8a, 0xce, - 0x2a, 0x0e, 0x47, 0xbe, 0x34, 0x8b, 0x70, 0xd8, 0xf1, 0xff, 0x32, 0xdc, 0x01, 0x2c, 0x96, 0x7d, - 0x67, 0xbb, 0x05, 0x60, 0xbf, 0x08, 0xd8, 0x2f, 0x07, 0xbc, 0x35, 0xc3, 0x09, 0x80, 0xbb, 0xd0, - 0xc9, 0xbf, 0xb0, 0x28, 0xb9, 0xbc, 0x9f, 0x89, 0xc2, 0xd0, 0x47, 0x17, 0x9a, 0x2f, 0xbe, 0xa9, - 0x10, 0x95, 0xc6, 0xc3, 0x14, 0x66, 0xc2, 0xb5, 0xfc, 0xaf, 0xa0, 0xae, 0x34, 0x44, 0x18, 0xec, - 0xb9, 0xfa, 0x4e, 0x97, 0xff, 0x26, 0xf7, 0x01, 0x86, 0x76, 0xf2, 0xe3, 0x88, 0xc6, 0x36, 0x06, - 0xc8, 0x75, 0x33, 0x23, 0x91, 0xbd, 0xf0, 0x22, 0x6b, 0xc8, 0xe3, 0xe7, 0x69, 0xd5, 0x0b, 0x2f, - 0x7a, 0xcd, 0x63, 0xed, 0x75, 0x80, 0x8b, 0x2b, 0xdf, 0x0e, 0x64, 0xad, 0x0c, 0x2e, 0x1b, 0x42, - 0xc2, 0xab, 0x8d, 0x3f, 0xae, 0x40, 0x3b, 0xf7, 0xfd, 0x99, 0x7c, 0x00, 0x2d, 0x81, 0x46, 0x03, - 0xfb, 0xc4, 0xa7, 0x92, 0x67, 0xdd, 0x6c, 0x72, 0xd9, 0xae, 0x14, 0xf1, 0x3d, 0x4a, 0x62, 0x2a, - 0x1d, 0xc9, 0xa9, 0x25, 0x84, 0x4a, 0x69, 0x03, 0xba, 0x39, 0x25, 0xeb, 0xa2, 0x8f, 0xb7, 0xbd, - 0x9d, 0xac, 0xde, 0x9b, 0xbe, 0xf1, 0x8f, 0x15, 0x58, 0x2c, 0x7b, 0x3f, 0x42, 0x3e, 0xce, 0xac, - 0xaa, 0x95, 0xd2, 0x3c, 0x15, 0x57, 0xf3, 0xcf, 0xa1, 0xe6, 0xdb, 0x27, 0xd4, 0x57, 0xc9, 0xd7, - 0xc7, 0x37, 0xbc, 0x4a, 0x79, 0xfc, 0x4a, 0x68, 0xe2, 0xa7, 0x28, 0x69, 0xb6, 0xf6, 0x02, 0x9a, - 0x19, 0xf1, 0x7b, 0xc5, 0x46, 0x3f, 0x2f, 0x92, 0xc7, 0x59, 0xbe, 0x2d, 0x79, 0x63, 0x07, 0xba, - 0x45, 0x79, 0xfe, 0x9e, 0xbe, 0x52, 0xbc, 0xa7, 0x2f, 0xbb, 0xe4, 0xff, 0x87, 0x0a, 0xcc, 0x17, - 0x1e, 0xb8, 0x10, 0x23, 0x43, 0x81, 0x14, 0xdf, 0xaf, 0xe0, 0xd0, 0x7d, 0x59, 0x18, 0x3a, 0xa3, - 0xfc, 0xb1, 0xcc, 0xff, 0xf4, 0xa8, 0x3d, 0xcb, 0xb0, 0xc5, 0x01, 0xbb, 0x05, 0x5b, 0xe3, 0x03, - 0x68, 0x66, 0x44, 0xa5, 0xdf, 0x89, 0x8e, 0x01, 0xe4, 0x3b, 0x95, 0x63, 0x4c, 0x2b, 0xb9, 0xe7, - 0xa2, 0x17, 0x8b, 0xdf, 0x82, 0x15, 0xf7, 0x40, 0x74, 0x5b, 0x59, 0xe0, 0x43, 0xae, 0xbf, 0x7d, - 0xaa, 0xcf, 0x12, 0x5a, 0x60, 0xfc, 0xed, 0x0c, 0x34, 0x33, 0x2f, 0x77, 0xc8, 0x87, 0x99, 0x14, - 0x36, 0xdd, 0x87, 0x85, 0x46, 0xfa, 0xc1, 0x90, 0x7c, 0xc1, 0xd7, 0x92, 0x7c, 0x7e, 0x25, 0xb4, - 0xe5, 0xae, 0x7d, 0x47, 0x6f, 0x14, 0x7c, 0xc9, 0x0b, 0x75, 0xf0, 0x22, 0xf5, 0x9b, 0x0f, 0xa3, - 0x9b, 0x30, 0x95, 0x25, 0xb9, 0x09, 0x23, 0x06, 0xb4, 0xc5, 0x1d, 0x5e, 0xe8, 0xca, 0x7b, 0x25, - 0x5c, 0xc6, 0x4d, 0x37, 0x61, 0xfb, 0xa1, 0x2b, 0xae, 0x91, 0xc8, 0x7d, 0x68, 0x6a, 0x1d, 0x2f, - 0x52, 0xdf, 0x76, 0x50, 0x63, 0x10, 0xf1, 0x38, 0x35, 0xb1, 0x87, 0xd4, 0x4a, 0x46, 0x27, 0x01, - 0x65, 0xe2, 0x9b, 0x73, 0xdd, 0x04, 0x2e, 0x3a, 0x12, 0x12, 0xbe, 0xee, 0x79, 0x04, 0x19, 0x8e, - 0xd8, 0x59, 0xe8, 0x05, 0x67, 0xe2, 0x7e, 0xbf, 0x6e, 0x36, 0x03, 0x9b, 0x1d, 0xa0, 0x88, 0x7c, - 0x04, 0x1d, 0x3f, 0x74, 0x6c, 0xdf, 0x52, 0xd9, 0xab, 0xb8, 0xe0, 0xaf, 0x9b, 0x6d, 0x21, 0x55, - 0xe7, 0x1d, 0xd9, 0x84, 0x26, 0x13, 0x33, 0x20, 0x3b, 0x2d, 0xdf, 0x23, 0xaa, 0x4e, 0xa7, 0x73, - 0x63, 0x02, 0x4b, 0xe7, 0xa9, 0xaf, 0xdd, 0x50, 0x26, 0x3a, 0xf7, 0xc7, 0x5f, 0x4b, 0x95, 0xb9, - 0x20, 0xdf, 0xdd, 0xed, 0x04, 0x2f, 0x06, 0x5a, 0x72, 0xeb, 0x53, 0x65, 0xf2, 0x04, 0x16, 0xd3, - 0x8f, 0xe1, 0x99, 0xa3, 0xb5, 0x2d, 0x2f, 0xf3, 0x74, 0xdd, 0xa1, 0x3a, 0x63, 0xff, 0x3b, 0x0e, - 0xfd, 0x00, 0xfd, 0x03, 0x9d, 0x19, 0x27, 0xb1, 0xaa, 0x27, 0xd1, 0xf8, 0xb7, 0x0a, 0xac, 0x4e, - 0x7c, 0x8a, 0x25, 0x3c, 0x99, 0x6f, 0xd0, 0xca, 0x93, 0xf9, 0xd6, 0x8d, 0xe9, 0x72, 0x35, 0x4d, - 0x97, 0x73, 0x27, 0xea, 0x74, 0xfe, 0x44, 0xe5, 0x1b, 0x6e, 0x64, 0xc7, 0x34, 0x60, 0x96, 0x4b, - 0xc5, 0x75, 0x9f, 0x17, 0xa1, 0xa3, 0x74, 0xa4, 0x7c, 0x47, 0x88, 0x65, 0x44, 0x3a, 0xb4, 0x1d, - 0xbe, 0x21, 0x4b, 0x37, 0x99, 0x1d, 0xda, 0xce, 0x9b, 0x7e, 0xfe, 0x34, 0xac, 0xe5, 0x4f, 0x43, - 0xf2, 0x13, 0x20, 0x45, 0xf4, 0x8b, 0xbe, 0x70, 0xa3, 0x86, 0xd9, 0xcd, 0xe3, 0x5f, 0xf4, 0x8d, - 0xcf, 0x4b, 0xfb, 0x8a, 0x63, 0x53, 0xd2, 0x57, 0xe3, 0x37, 0x15, 0x58, 0x99, 0xf0, 0x20, 0xec, - 0xc6, 0x13, 0x3c, 0x1f, 0x34, 0x55, 0x8b, 0x41, 0xd3, 0x63, 0x58, 0xf0, 0x02, 0x46, 0xe3, 0x53, - 0x5b, 0x32, 0xce, 0x0d, 0xdd, 0x1d, 0x5d, 0xa5, 0xf2, 0x15, 0xe3, 0x59, 0x09, 0x8b, 0x77, 0xc7, - 0x11, 0xc6, 0x9f, 0x57, 0x60, 0x75, 0xe2, 0xd3, 0xa7, 0x1b, 0xf9, 0x1b, 0xd0, 0x4e, 0xf9, 0xf3, - 0x19, 0x91, 0x5d, 0x68, 0xea, 0x2e, 0xbc, 0xe9, 0x8f, 0x75, 0xa2, 0x3f, 0xb1, 0x13, 0x32, 0x70, - 0x79, 0x5e, 0x4a, 0xe6, 0x16, 0xdd, 0xf8, 0xa7, 0x0a, 0x2c, 0x95, 0x3e, 0x6d, 0x23, 0x9b, 0xb0, - 0xa4, 0x2e, 0x91, 0x1d, 0x7f, 0x94, 0x30, 0x1a, 0x5b, 0x3c, 0x34, 0x51, 0x97, 0xa0, 0x0b, 0x58, - 0xb9, 0x2d, 0xeb, 0xb6, 0x79, 0x15, 0x79, 0x9a, 0xbe, 0xf2, 0xa4, 0x57, 0x8c, 0xc6, 0x81, 0xed, - 0xa3, 0x51, 0x15, 0x3f, 0x72, 0xca, 0xda, 0x5d, 0xac, 0x94, 0x56, 0x3f, 0x83, 0x35, 0x65, 0xc5, - 0x37, 0x93, 0x13, 0xdb, 0xb7, 0x03, 0x47, 0x37, 0x27, 0x73, 0xb0, 0x1e, 0x6a, 0xbc, 0xca, 0x28, - 0x08, 0x6b, 0xe3, 0x9f, 0x2b, 0xd0, 0xce, 0xbd, 0x87, 0x2b, 0xcd, 0x03, 0x73, 0xa7, 0x6b, 0xb5, - 0xe4, 0x74, 0xd5, 0xef, 0x42, 0x1a, 0xb8, 0x91, 0xaf, 0x03, 0xa8, 0x7e, 0xeb, 0x55, 0xd5, 0x40, - 0xc9, 0x20, 0xe2, 0xd9, 0x62, 0x8e, 0xac, 0xde, 0x80, 0x3b, 0x59, 0xf1, 0x20, 0xe2, 0x9b, 0xac, - 0x1e, 0x0b, 0x2f, 0x52, 0x97, 0x56, 0x4d, 0x25, 0x1b, 0x44, 0x3c, 0x4f, 0x6a, 0xe7, 0x9e, 0xe4, - 0xbd, 0x7f, 0x0f, 0x3e, 0xdd, 0x80, 0x86, 0xce, 0x08, 0xc8, 0x1c, 0x4c, 0x6f, 0xed, 0xff, 0xa2, - 0x3b, 0x45, 0xea, 0x30, 0x33, 0x38, 0x7c, 0xf3, 0xb4, 0x3b, 0x83, 0xbf, 0xfa, 0xdd, 0xda, 0xa7, - 0x7f, 0x56, 0x81, 0x86, 0x3e, 0xb4, 0x48, 0x1b, 0x1a, 0xdb, 0x83, 0x1d, 0xd3, 0x1a, 0xec, 0x7f, - 0x7d, 0xd0, 0x9d, 0x22, 0x0b, 0x30, 0x6f, 0xee, 0xbe, 0x3e, 0x38, 0xde, 0xb5, 0x7e, 0x38, 0x30, - 0xbf, 0x7b, 0x75, 0xb0, 0xb5, 0xd3, 0xad, 0x90, 0x79, 0x68, 0xa2, 0x70, 0xef, 0xe0, 0xe8, 0xb8, - 0x5b, 0x25, 0x04, 0x3a, 0xaf, 0x0e, 0xb6, 0xb7, 0x5e, 0xa5, 0x4a, 0xd3, 0xa4, 0x03, 0x20, 0x65, - 0x42, 0x67, 0x86, 0xdc, 0x81, 0x36, 0x1a, 0x1d, 0x7f, 0xbf, 0xbf, 0xbf, 0xfb, 0xaa, 0x3b, 0x4b, - 0xba, 0xd0, 0x92, 0x2a, 0x28, 0xa9, 0x7d, 0xfa, 0x02, 0x20, 0x3d, 0x11, 0x39, 0xc7, 0xfd, 0x83, - 0xfd, 0xdd, 0xee, 0x14, 0x69, 0x41, 0x7d, 0xff, 0xc0, 0xda, 0xdd, 0xdf, 0xde, 0x3a, 0xec, 0x56, - 0x48, 0x03, 0x66, 0xc5, 0xce, 0xd2, 0xad, 0xca, 0x6e, 0x0c, 0x0e, 0xbb, 0xd3, 0x9b, 0x5f, 0x01, - 0xc8, 0x07, 0x0e, 0xe2, 0x9f, 0x2c, 0x9e, 0xc0, 0x8c, 0xf8, 0xab, 0x82, 0x88, 0xcc, 0xff, 0x78, - 0xac, 0x29, 0x59, 0xe6, 0xff, 0x3c, 0x9e, 0x54, 0x5e, 0xce, 0xfd, 0xfe, 0xac, 0xf8, 0xfa, 0x7b, - 0x52, 0x13, 0x7f, 0xbe, 0xf8, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x1d, 0x28, 0x03, 0x35, - 0x32, 0x00, 0x00, + // 4052 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0xcb, 0x73, 0x1c, 0x37, + 0x7a, 0xe7, 0x0c, 0xc9, 0xe1, 0xcc, 0x37, 0x0f, 0x8e, 0xc0, 0x87, 0x86, 0xd4, 0xd3, 0x2d, 0x2b, + 0xa6, 0x9d, 0xb5, 0xac, 0xc8, 0xd2, 0x68, 0xe5, 0x6c, 0xbc, 0x45, 0x91, 0xb4, 0x39, 0xb6, 0x44, + 0x32, 0x4d, 0x9a, 0xce, 0x6e, 0x6d, 0x55, 0xa7, 0xd9, 0x0d, 0x92, 0x1d, 0xf5, 0x74, 0xb7, 0xbb, + 0x31, 0x7c, 0x6c, 0x4e, 0xd9, 0x6c, 0xaa, 0x92, 0x4a, 0xa5, 0x72, 0x4b, 0xe5, 0x94, 0x53, 0x4e, + 0xa9, 0xfc, 0x07, 0x39, 0x24, 0x97, 0x54, 0x65, 0x2b, 0xff, 0x49, 0x6e, 0x39, 0xe4, 0x9e, 0x02, + 0xf0, 0x01, 0xfd, 0x98, 0x1e, 0x8a, 0x8a, 0x9d, 0x3d, 0x71, 0xf0, 0x3d, 0x7e, 0xf8, 0x01, 0xf8, + 0x00, 0x7c, 0x40, 0x83, 0x40, 0x8e, 0xa9, 0xef, 0x5d, 0x1c, 0xd9, 0xce, 0x1b, 0x1a, 0xb8, 0x8f, + 0xa2, 0x38, 0x64, 0x21, 0x99, 0x15, 0x32, 0xa3, 0x0d, 0xcd, 0xfd, 0xcb, 0xc0, 0x31, 0xe9, 0x77, + 0x23, 0x9a, 0x30, 0xe3, 0x3f, 0x97, 0xa1, 0x79, 0x10, 0x6e, 0xda, 0xcc, 0x8e, 0x7c, 0x3b, 0xa0, + 0xe4, 0x03, 0x98, 0x4f, 0xb8, 0x2a, 0x70, 0xa8, 0x15, 0x8c, 0x86, 0x47, 0x34, 0xee, 0xcd, 0xdf, + 0xaf, 0xac, 0xcd, 0x98, 0x1d, 0x25, 0xde, 0x11, 0x52, 0xb2, 0x06, 0x73, 0x5e, 0x60, 0x25, 0x97, + 0x81, 0xd3, 0xab, 0xdc, 0xaf, 0xac, 0x35, 0x9f, 0xb4, 0x1f, 0x89, 0x0a, 0x1e, 0x0d, 0x02, 0x8e, + 0xbf, 0x3d, 0x65, 0xd6, 0x3c, 0xf1, 0x8b, 0x3c, 0x87, 0x96, 0x17, 0x25, 0x94, 0x59, 0xa3, 0xc8, + 0xb5, 0x19, 0xed, 0x55, 0x85, 0x39, 0x51, 0xe6, 0x7b, 0xfb, 0x94, 0x7d, 0x23, 0x34, 0xdb, 0x53, + 0x66, 0x53, 0x58, 0xca, 0x22, 0xf9, 0x12, 0x88, 0x74, 0x74, 0xa9, 0xcf, 0x6c, 0xe5, 0x3e, 0x2d, + 0xdc, 0x6f, 0x66, 0xdd, 0x37, 0xb9, 0x5e, 0x63, 0x74, 0x85, 0x53, 0x46, 0x96, 0x32, 0x88, 0xe9, + 0x30, 0x3c, 0xa3, 0xbd, 0x99, 0x71, 0x06, 0xa6, 0xd0, 0x68, 0x06, 0xb2, 0x48, 0xf6, 0x60, 0xc9, + 0x76, 0x98, 0x77, 0x46, 0xad, 0x28, 0x0e, 0x8f, 0x3d, 0x9f, 0x2a, 0x12, 0xb3, 0x02, 0x61, 0x15, + 0x11, 0xd6, 0x85, 0xcd, 0x9e, 0x34, 0xd1, 0x3c, 0x16, 0xec, 0x71, 0x71, 0x09, 0x22, 0x72, 0xaa, + 0x4d, 0x46, 0xd4, 0xdc, 0xf2, 0x88, 0xc8, 0xf1, 0x35, 0x2c, 0x2a, 0xc4, 0xd0, 0xf7, 0x9c, 0x4b, + 0x45, 0x71, 0x4e, 0x00, 0xae, 0xe4, 0x01, 0x85, 0x85, 0x66, 0x48, 0xec, 0x31, 0xe9, 0x38, 0x1c, + 0xf2, 0xab, 0x4f, 0x84, 0xd3, 0xf4, 0x72, 0x70, 0x29, 0xbb, 0xd3, 0x30, 0x61, 0x16, 0x0d, 0xdc, + 0x28, 0xf4, 0x02, 0x1d, 0x04, 0x8d, 0x1c, 0xdc, 0x76, 0x98, 0xb0, 0x2d, 0xb4, 0x48, 0xd9, 0x9d, + 0x8e, 0x49, 0xc7, 0xe1, 0x90, 0x1d, 0x4c, 0x84, 0x4b, 0xd9, 0x9d, 0x8e, 0x49, 0xc9, 0xcf, 0xa0, + 0x77, 0x1e, 0xc6, 0x6f, 0xfc, 0xd0, 0x76, 0xc7, 0x18, 0x36, 0x05, 0xe4, 0x1d, 0x84, 0xfc, 0x16, + 0xcd, 0xc6, 0x58, 0x2e, 0x9f, 0x97, 0x6a, 0xca, 0xa1, 0x91, 0x6d, 0xeb, 0x4a, 0x68, 0xcd, 0x78, + 0x0c, 0x1a, 0x59, 0x7f, 0x06, 0x6d, 0x27, 0x0c, 0x8e, 0xbd, 0x13, 0x45, 0xb5, 0x2d, 0xf0, 0x16, + 0x10, 0x6f, 0x43, 0xe8, 0x34, 0xc1, 0x96, 0x93, 0x29, 0xeb, 0x0e, 0x1c, 0x52, 0x66, 0xbb, 0x76, + 0x3a, 0xab, 0x3a, 0x63, 0x1d, 0xf8, 0x1a, 0x2d, 0xf2, 0xe3, 0x91, 0x97, 0x8e, 0xc3, 0x61, 0x0b, + 0xc9, 0x44, 0xb8, 0xfc, 0x78, 0xe4, 0xa5, 0xe4, 0xe7, 0xb0, 0x92, 0x87, 0x3b, 0x7b, 0x7a, 0xd6, + 0x57, 0x14, 0x1f, 0xe6, 0x7a, 0x2d, 0x8b, 0x79, 0xf8, 0xf4, 0xb0, 0x9f, 0x0e, 0xc8, 0x69, 0x4e, + 0x73, 0x86, 0x9a, 0x09, 0xd8, 0xc8, 0xf7, 0x77, 0xae, 0xc4, 0x4e, 0x47, 0xa4, 0x88, 0x8d, 0xbc, + 0xd7, 0xa1, 0xeb, 0x45, 0xf6, 0xd0, 0x8a, 0xc2, 0xd0, 0x57, 0x74, 0xbb, 0x02, 0x72, 0x49, 0x2f, + 0x32, 0xeb, 0xaf, 0xf7, 0xc2, 0xd0, 0xd7, 0x34, 0x3b, 0xdc, 0x21, 0x95, 0xe4, 0x21, 0x90, 0xd5, + 0x8d, 0x52, 0x08, 0xcd, 0x46, 0x43, 0x20, 0x8b, 0x7d, 0x58, 0x4e, 0x68, 0x7c, 0xe6, 0x39, 0xd4, + 0xb2, 0x1d, 0x27, 0x1c, 0xa5, 0xb1, 0xbc, 0x20, 0x80, 0x6e, 0x21, 0xd0, 0xbe, 0x34, 0x5a, 0x97, + 0x36, 0x9a, 0xd1, 0x62, 0x52, 0x22, 0x2f, 0x03, 0x45, 0x76, 0x8b, 0x57, 0x80, 0x6a, 0x8e, 0x05, + 0x50, 0x64, 0xba, 0x01, 0xdd, 0xc0, 0x1e, 0xd2, 0x24, 0xb2, 0x1d, 0xbd, 0xa4, 0x2e, 0x09, 0xb8, + 0x65, 0x84, 0xdb, 0x51, 0x6a, 0x4d, 0x6f, 0x3e, 0xc8, 0x8b, 0xf2, 0x20, 0xc8, 0x69, 0xb9, 0x1c, + 0x44, 0xd3, 0x49, 0x41, 0x90, 0xc9, 0x73, 0x68, 0xc5, 0xe1, 0x88, 0x69, 0x16, 0x37, 0x73, 0x5b, + 0x83, 0xc9, 0x55, 0xe9, 0xe6, 0x14, 0xa7, 0xc5, 0xd4, 0x11, 0x6b, 0xee, 0x8d, 0x3b, 0xa6, 0x7b, + 0x4a, 0x9c, 0x16, 0xc9, 0x06, 0x34, 0xcf, 0x18, 0x8d, 0x54, 0x85, 0x2b, 0xc2, 0xef, 0x3e, 0xfa, + 0x1d, 0xfe, 0xd1, 0xab, 0xf5, 0x9d, 0x83, 0x51, 0x10, 0x50, 0x7f, 0x6c, 0xa5, 0x01, 0xee, 0xa6, + 0xdb, 0x2e, 0x41, 0xb0, 0xf2, 0xd5, 0xb7, 0x81, 0x68, 0x2a, 0x02, 0x04, 0x99, 0xfc, 0x02, 0x56, + 0xce, 0xbd, 0x98, 0x9e, 0x8c, 0xec, 0x78, 0x7c, 0xf9, 0xbb, 0x25, 0x20, 0xef, 0xaa, 0x35, 0x4a, + 0xd9, 0x8d, 0xb1, 0xba, 0x79, 0x5e, 0xae, 0x9a, 0x80, 0x8e, 0x84, 0x6f, 0x5f, 0x8d, 0xae, 0xe9, + 0x8e, 0xa3, 0x23, 0xf7, 0x6f, 0xa1, 0x77, 0xe2, 0x87, 0x47, 0xb6, 0x6f, 0x1d, 0x9d, 0x44, 0x56, + 0x7e, 0x39, 0xbc, 0x23, 0xc0, 0x6f, 0x23, 0xf8, 0x97, 0xc2, 0xec, 0xe5, 0x97, 0x7b, 0x85, 0x75, + 0x71, 0x49, 0xfa, 0xbf, 0x3c, 0x89, 0xb2, 0x0a, 0xf2, 0x13, 0x68, 0xd3, 0xc0, 0xb1, 0xa3, 0x64, + 0xe4, 0xdb, 0xcc, 0x0b, 0x83, 0xde, 0x5d, 0x81, 0xb6, 0x88, 0x68, 0x5b, 0x59, 0xdd, 0xf6, 0x94, + 0x99, 0x37, 0x26, 0x7f, 0x00, 0x1d, 0x35, 0x5b, 0x90, 0xcc, 0xbd, 0x9c, 0x3b, 0xce, 0x12, 0x4d, + 0xa2, 0x9d, 0x64, 0x05, 0x59, 0x77, 0xec, 0xa8, 0xfb, 0x65, 0xee, 0xba, 0x7b, 0x94, 0x3b, 0x76, + 0x8a, 0x03, 0xb7, 0x4b, 0xba, 0x3c, 0x5d, 0x41, 0xdf, 0xcb, 0x85, 0xc9, 0x58, 0xaf, 0x67, 0x16, + 0xd1, 0x95, 0xf3, 0x49, 0xca, 0xc9, 0x95, 0x20, 0x63, 0xe3, 0x6d, 0x95, 0x68, 0xf6, 0x65, 0x95, + 0x60, 0x4b, 0x0e, 0xe0, 0x66, 0x61, 0xb1, 0xd6, 0x8d, 0x78, 0x90, 0x5b, 0x76, 0x72, 0x4b, 0x75, + 0xca, 0x7f, 0xf1, 0xb4, 0x44, 0x5e, 0x8a, 0x8a, 0xac, 0xdf, 0xbf, 0x02, 0x35, 0x5d, 0xcc, 0x4e, + 0x4b, 0xe4, 0x2f, 0x1b, 0x30, 0x17, 0xd9, 0x97, 0x7c, 0x9f, 0x36, 0xfe, 0x66, 0x16, 0xda, 0x5f, + 0xc4, 0xe1, 0xf0, 0xca, 0x7c, 0xba, 0x5e, 0x9a, 0x4f, 0xef, 0xc1, 0x52, 0x14, 0x87, 0x0e, 0x4d, + 0x12, 0x2b, 0x61, 0x36, 0x1b, 0x25, 0xf9, 0x7c, 0x57, 0x25, 0x86, 0x7b, 0xd2, 0x66, 0x5f, 0x98, + 0xa4, 0xa9, 0x66, 0x34, 0x2e, 0x26, 0x7f, 0x0c, 0xb7, 0xf2, 0xb9, 0x52, 0x1e, 0x57, 0x26, 0xc1, + 0xf7, 0x4a, 0x52, 0xa6, 0x02, 0x78, 0xef, 0x74, 0x82, 0x6e, 0x62, 0x0d, 0xd8, 0xa7, 0xb3, 0x6f, + 0xa9, 0x41, 0xf7, 0x6b, 0x49, 0x0d, 0x18, 0x07, 0x3e, 0xdc, 0x1b, 0xcf, 0xa2, 0xf2, 0xed, 0x90, + 0x89, 0xf3, 0x83, 0x09, 0xc9, 0x54, 0xa1, 0x2d, 0xb7, 0xcf, 0xaf, 0xd0, 0x5f, 0x59, 0x1b, 0xb6, + 0x69, 0xee, 0x1a, 0xb5, 0xe9, 0x76, 0x4d, 0xa8, 0x0d, 0xdb, 0x76, 0x08, 0xe9, 0xea, 0x56, 0x68, + 0x53, 0x23, 0xb7, 0x82, 0xe9, 0x39, 0x54, 0x68, 0xcc, 0xd2, 0x79, 0x99, 0x22, 0x1b, 0x8f, 0xbf, + 0xaa, 0x40, 0x2b, 0xb7, 0xba, 0x3d, 0x87, 0x9a, 0x5c, 0x2b, 0x7b, 0x95, 0xfb, 0xd3, 0x99, 0xc1, + 0xc9, 0x1a, 0x61, 0x61, 0x2b, 0x60, 0xf1, 0xa5, 0x89, 0xe6, 0xab, 0x2f, 0xa0, 0x99, 0x11, 0x93, + 0x2e, 0x4c, 0xbf, 0xa1, 0x97, 0xe2, 0xe4, 0xd7, 0x30, 0xf9, 0x4f, 0xb2, 0x08, 0xb3, 0x67, 0xb6, + 0x3f, 0x92, 0xc7, 0xbb, 0x86, 0x29, 0x0b, 0x9f, 0x55, 0x7f, 0x5c, 0x31, 0xea, 0x50, 0x93, 0x67, + 0x42, 0xe3, 0xef, 0x2b, 0xd0, 0xcc, 0x9c, 0xf7, 0x48, 0x07, 0xaa, 0x9e, 0x8b, 0x20, 0x55, 0xcf, + 0x25, 0x3d, 0x98, 0x1b, 0x52, 0x3e, 0x1b, 0x92, 0x5e, 0xf5, 0xfe, 0xf4, 0x5a, 0xc3, 0x54, 0x45, + 0xf2, 0x18, 0x66, 0xd8, 0x65, 0x24, 0x27, 0x43, 0x47, 0x77, 0x4c, 0x06, 0x4b, 0xfe, 0x3e, 0xb8, + 0x8c, 0xa8, 0x29, 0x2c, 0x8d, 0x8f, 0xa1, 0xa1, 0x45, 0xa4, 0x06, 0xd5, 0xc1, 0x5e, 0x77, 0x8a, + 0xcc, 0xf3, 0xfa, 0xad, 0xf5, 0x9d, 0x4d, 0x6b, 0x6f, 0xd7, 0x3c, 0xe8, 0x56, 0xc8, 0x1c, 0x4c, + 0xef, 0x6c, 0x1d, 0x74, 0xab, 0x46, 0x04, 0xdd, 0xe2, 0x51, 0x72, 0x8c, 0xde, 0x03, 0x68, 0xdb, + 0xae, 0x4b, 0x5d, 0x2b, 0x4f, 0xb2, 0x25, 0x84, 0xaf, 0x91, 0xe9, 0x07, 0x30, 0x2f, 0x43, 0x25, + 0x35, 0x9b, 0x16, 0x66, 0x1d, 0x14, 0xa3, 0xa1, 0x71, 0x07, 0xfb, 0x02, 0xa3, 0xa1, 0x50, 0x99, + 0x61, 0xc3, 0x42, 0xc9, 0xb1, 0x92, 0xdc, 0xd7, 0x66, 0xcd, 0x27, 0xdd, 0x74, 0x4d, 0xe0, 0x16, + 0x83, 0x4d, 0xc1, 0x72, 0x0d, 0xe6, 0xf0, 0x68, 0x89, 0x27, 0xed, 0x4e, 0xde, 0xcc, 0x54, 0x6a, + 0xe3, 0x79, 0xa1, 0x0a, 0x64, 0xf2, 0xd6, 0x2a, 0x8c, 0x7b, 0xd0, 0xd0, 0x02, 0x42, 0x60, 0x86, + 0x27, 0x55, 0x48, 0x5d, 0xfc, 0x36, 0x42, 0x98, 0x43, 0x03, 0xf2, 0x18, 0xda, 0x5e, 0x70, 0x14, + 0x8e, 0x02, 0xd7, 0x8a, 0x47, 0x3e, 0x4d, 0x30, 0xf0, 0x9a, 0x2a, 0x51, 0x1a, 0xf9, 0xd4, 0x6c, + 0xa1, 0x05, 0x2f, 0x24, 0xe4, 0x09, 0x74, 0xc2, 0x11, 0xcb, 0xba, 0x54, 0xc7, 0x5d, 0xda, 0xca, + 0x44, 0xf8, 0x18, 0xbf, 0x00, 0x32, 0x7e, 0xc2, 0x25, 0xf7, 0x32, 0x2d, 0x99, 0x57, 0x2d, 0x11, + 0x06, 0xd8, 0x57, 0x0f, 0xa1, 0x26, 0x4f, 0xb9, 0xd8, 0x55, 0xed, 0x9c, 0x91, 0x89, 0x4a, 0xe3, + 0x59, 0x1e, 0x1d, 0xfb, 0xe9, 0x6d, 0xe8, 0xc6, 0x13, 0xa8, 0xab, 0x32, 0xef, 0x25, 0xe6, 0xd1, + 0x58, 0xf5, 0x12, 0xff, 0xad, 0x7b, 0xae, 0x9a, 0xe9, 0xb9, 0x7f, 0xaf, 0x40, 0x4d, 0x3a, 0x91, + 0xdb, 0xd0, 0xd0, 0xd9, 0xaa, 0x58, 0x4b, 0x1b, 0x66, 0x2a, 0xf8, 0xed, 0xf4, 0x2b, 0xe7, 0x30, + 0x0a, 0x58, 0x6c, 0x3b, 0x6f, 0xa8, 0x2b, 0x26, 0x5f, 0xdd, 0x4c, 0x05, 0x64, 0x05, 0xea, 0x51, + 0x4c, 0x2d, 0x37, 0xb0, 0x99, 0xd8, 0x4e, 0xea, 0x3c, 0xb6, 0xe8, 0x66, 0x60, 0x33, 0xe3, 0x9f, + 0xba, 0x30, 0xc3, 0x21, 0xc8, 0x32, 0xd4, 0x6c, 0x47, 0x24, 0x52, 0xb2, 0xe9, 0x58, 0x22, 0x9f, + 0x00, 0x78, 0x91, 0x75, 0x46, 0xe3, 0x84, 0xeb, 0xaa, 0x62, 0x5e, 0x77, 0xf5, 0xbc, 0x3e, 0x94, + 0x72, 0xb3, 0xe1, 0x45, 0xf8, 0x93, 0xfc, 0x2e, 0xaf, 0x2c, 0x64, 0xa1, 0x13, 0xfa, 0xb8, 0x27, + 0xce, 0xa7, 0xc1, 0x29, 0xc4, 0xa6, 0x36, 0x20, 0x37, 0x61, 0x2e, 0x89, 0x1d, 0x2b, 0xa0, 0x9c, + 0x18, 0x9f, 0x7d, 0xb5, 0x24, 0x76, 0x76, 0x28, 0x23, 0x1f, 0x43, 0x83, 0x2b, 0xa2, 0x30, 0x66, + 0x49, 0x6f, 0x56, 0xb4, 0x5f, 0xc7, 0x78, 0x18, 0x33, 0xd3, 0x0e, 0x4e, 0xa8, 0x59, 0x4f, 0x62, + 0x87, 0x97, 0x12, 0xf2, 0x1c, 0x56, 0x04, 0x8e, 0x3d, 0xa4, 0xae, 0x70, 0xb2, 0xbc, 0xc8, 0x4a, + 0x28, 0xb3, 0x3c, 0x37, 0xe9, 0xb5, 0x04, 0xf2, 0x22, 0x47, 0xe6, 0x7a, 0xee, 0x31, 0x88, 0xf6, + 0x29, 0x1b, 0xb8, 0x09, 0x27, 0xe0, 0x26, 0x4c, 0x10, 0xa8, 0x49, 0x02, 0x6e, 0xc2, 0x90, 0x00, + 0x57, 0x48, 0x02, 0x73, 0x93, 0x08, 0xb8, 0x09, 0xd3, 0x04, 0x04, 0x4e, 0x29, 0x81, 0xb6, 0x24, + 0xc0, 0x91, 0xc7, 0x08, 0xdc, 0x81, 0x86, 0xe7, 0x0c, 0x23, 0x4b, 0x2c, 0x9b, 0x3c, 0xe5, 0x98, + 0xdd, 0x9e, 0x32, 0xeb, 0x5c, 0x24, 0x56, 0xc4, 0xcf, 0xa1, 0xa3, 0xd5, 0x96, 0x13, 0xba, 0x6a, + 0xcf, 0x51, 0x47, 0xa7, 0x01, 0x1a, 0xae, 0x07, 0xee, 0x46, 0xe8, 0x8a, 0x7b, 0x04, 0xe5, 0xcb, + 0xcb, 0xe4, 0x01, 0x74, 0x78, 0xc7, 0x64, 0xc8, 0x80, 0x20, 0xd3, 0x4c, 0x62, 0x47, 0x73, 0x78, + 0x00, 0x1d, 0x4e, 0x3e, 0x63, 0xd4, 0x94, 0x46, 0x6e, 0x92, 0x12, 0xfd, 0x11, 0x2c, 0xa0, 0x91, + 0x68, 0x9e, 0xb2, 0x9c, 0x17, 0x96, 0xf3, 0xc2, 0x92, 0x37, 0x0c, 0xad, 0x9f, 0x40, 0x2b, 0x08, + 0x99, 0xa5, 0x23, 0xe1, 0xb8, 0x3c, 0x12, 0x9a, 0x41, 0xc8, 0x54, 0x81, 0xdc, 0x05, 0x5e, 0xb4, + 0x54, 0x40, 0x9c, 0x08, 0xe4, 0x46, 0x10, 0xb2, 0x7d, 0x19, 0x13, 0x4f, 0xa1, 0xad, 0xf4, 0x72, + 0x58, 0x4e, 0x27, 0x0c, 0x4b, 0x53, 0xfa, 0xc8, 0x91, 0x41, 0x54, 0x35, 0xca, 0x9e, 0x46, 0xdd, + 0x94, 0x03, 0x8d, 0xa8, 0xe9, 0x60, 0xff, 0xc9, 0x15, 0xa8, 0x9b, 0x6a, 0xbc, 0xdf, 0x97, 0x5e, + 0xe9, 0xd0, 0xbd, 0x11, 0x43, 0x57, 0x11, 0x56, 0x6a, 0x50, 0xc8, 0x16, 0x90, 0x9c, 0x95, 0x1c, + 0x41, 0xff, 0xca, 0x11, 0xac, 0x98, 0xf3, 0x19, 0x08, 0x31, 0x88, 0x1f, 0x49, 0x98, 0xc2, 0x40, + 0x0e, 0xe5, 0x76, 0x25, 0xdb, 0xaa, 0x87, 0x09, 0x6d, 0x0b, 0xe3, 0x19, 0x68, 0xdb, 0xcd, 0xcc, + 0x90, 0x7e, 0x0e, 0x77, 0x74, 0x87, 0x97, 0x06, 0x6e, 0x24, 0xdc, 0x6e, 0xe2, 0x10, 0x8c, 0xc5, + 0x2e, 0xfa, 0x4f, 0x0e, 0xfc, 0xef, 0xb4, 0xff, 0x66, 0x59, 0xec, 0x3f, 0x81, 0xa5, 0x30, 0xf6, + 0x4e, 0xbc, 0xc0, 0xf6, 0x05, 0x89, 0x84, 0xfa, 0xd4, 0x61, 0x61, 0xdc, 0x8b, 0xc5, 0x12, 0xb4, + 0xa0, 0x94, 0xfb, 0xb1, 0xb3, 0x8f, 0xaa, 0x9c, 0x0f, 0xaf, 0x58, 0xfb, 0x24, 0x79, 0x9f, 0xcd, + 0x84, 0x69, 0x9f, 0x2d, 0xb8, 0x97, 0xab, 0x27, 0xbd, 0x8e, 0xd0, 0xde, 0x4c, 0x78, 0xdf, 0xce, + 0xd4, 0xa8, 0x2f, 0x25, 0x4a, 0x61, 0x54, 0x9b, 0x0b, 0x30, 0xa3, 0x3c, 0x0c, 0xb6, 0x3a, 0x0f, + 0xf3, 0x02, 0x56, 0x34, 0x8c, 0xea, 0x7e, 0x0d, 0x70, 0x26, 0x00, 0x96, 0x95, 0xc1, 0x8e, 0xe8, + 0xf9, 0x89, 0xae, 0xb9, 0x0e, 0x38, 0x1f, 0x73, 0xcd, 0xf6, 0xc1, 0xef, 0xc1, 0x62, 0xa1, 0xaf, + 0xc5, 0x89, 0xb4, 0xf7, 0x6b, 0xb9, 0xdc, 0x93, 0x5c, 0x5f, 0x0b, 0x15, 0xd9, 0x84, 0xbb, 0x65, + 0x2e, 0x69, 0xbb, 0x7b, 0x7f, 0x21, 0x9d, 0x6f, 0x8d, 0x3b, 0xeb, 0x66, 0xe7, 0x2a, 0x96, 0x7c, + 0x65, 0xc5, 0xbf, 0x2a, 0x54, 0x2c, 0xc8, 0x8e, 0x57, 0x9c, 0x71, 0xc9, 0x54, 0xfc, 0xe7, 0x85, + 0x8a, 0x53, 0xe7, 0xb4, 0xe2, 0x6f, 0xe4, 0x9e, 0x50, 0xbc, 0x15, 0x1b, 0xda, 0xcc, 0x39, 0xed, + 0x5d, 0xe4, 0x4e, 0x6b, 0xf9, 0x4b, 0xb1, 0xd7, 0xdc, 0xc2, 0x5c, 0x4e, 0x74, 0x63, 0xb2, 0x72, + 0x0e, 0x9b, 0xe5, 0x94, 0x87, 0xbd, 0x7c, 0x3b, 0xac, 0xab, 0xa9, 0xe6, 0x60, 0x3f, 0x01, 0x38, + 0x65, 0x2c, 0x42, 0x9c, 0x5f, 0xe6, 0xb2, 0xba, 0xed, 0x83, 0x83, 0x3d, 0xe9, 0xdd, 0xe0, 0x36, + 0xca, 0xa1, 0xae, 0xce, 0xc7, 0xbd, 0x3f, 0xcd, 0x5d, 0x2c, 0xf3, 0xfd, 0x5c, 0x5f, 0xd8, 0x6a, + 0x23, 0x9e, 0xb5, 0xf3, 0x74, 0xc2, 0xf2, 0xdc, 0xde, 0x6f, 0x70, 0x8f, 0xe7, 0xe5, 0x81, 0xfb, + 0xb2, 0x06, 0x33, 0x7c, 0x89, 0x7a, 0x09, 0x50, 0x57, 0xcb, 0xd5, 0x57, 0xb5, 0xfa, 0x7f, 0x54, + 0xba, 0xbf, 0xa9, 0x98, 0xe0, 0x87, 0x27, 0x56, 0x14, 0xd3, 0x63, 0xef, 0xc2, 0xf8, 0x12, 0x16, + 0xca, 0xa8, 0xaf, 0x42, 0x5d, 0x07, 0xa1, 0x04, 0xd6, 0x65, 0x7e, 0xdc, 0x10, 0xa3, 0x86, 0x39, + 0xb8, 0x2c, 0x18, 0xff, 0x58, 0x81, 0x86, 0x6e, 0x94, 0x3c, 0x4e, 0xb0, 0xd3, 0xd0, 0x95, 0xc9, + 0x91, 0x38, 0x4e, 0x88, 0x22, 0x79, 0x0c, 0xb3, 0x91, 0xcd, 0x4e, 0x55, 0x06, 0xb4, 0x5a, 0xec, + 0x8f, 0x47, 0x7b, 0x36, 0x3b, 0x95, 0x3d, 0x23, 0x0d, 0x57, 0xbf, 0x86, 0x86, 0x96, 0x91, 0x65, + 0x98, 0xa5, 0x17, 0xb6, 0xc3, 0x24, 0xab, 0xed, 0x29, 0x53, 0x16, 0x49, 0x0f, 0x6a, 0xb2, 0x45, + 0x32, 0xa5, 0xdb, 0x9e, 0x32, 0xb1, 0xfc, 0xb2, 0x05, 0xc0, 0x71, 0xe4, 0x28, 0x18, 0x7f, 0x57, + 0x81, 0x56, 0xb6, 0x33, 0xc9, 0x17, 0xd0, 0xb4, 0x83, 0x20, 0x64, 0xe2, 0x12, 0x49, 0xa5, 0x72, + 0xef, 0x97, 0x74, 0xfb, 0xa3, 0xf5, 0xd4, 0x4c, 0x1e, 0xd0, 0xb2, 0x8e, 0xab, 0x9f, 0x43, 0xb7, + 0x68, 0xf0, 0x4e, 0x47, 0xb5, 0x17, 0x30, 0x5f, 0xd8, 0x36, 0x44, 0xe2, 0xca, 0xf7, 0x21, 0xee, + 0x3f, 0x2b, 0xcf, 0x56, 0x5c, 0x26, 0x36, 0x9c, 0xaa, 0x94, 0xf1, 0xdf, 0xc6, 0x2b, 0xa8, 0xeb, + 0x0d, 0xb7, 0x07, 0x35, 0xbc, 0xeb, 0xa8, 0x60, 0xe2, 0x81, 0x65, 0xb2, 0x98, 0x4d, 0x79, 0xb7, + 0xa7, 0x64, 0xd2, 0xfb, 0xb2, 0x0b, 0x1d, 0xa9, 0xb7, 0xc2, 0x58, 0x4c, 0x46, 0xe3, 0x19, 0x34, + 0xf4, 0x06, 0xc9, 0xf9, 0x1e, 0x7b, 0x71, 0xc2, 0x90, 0x83, 0x2c, 0x70, 0x12, 0xbe, 0x9d, 0x30, + 0x45, 0x82, 0xff, 0x36, 0xfe, 0xb6, 0x02, 0xa4, 0x78, 0x26, 0x1f, 0x6c, 0xf2, 0x33, 0x59, 0x18, + 0x3b, 0xa7, 0x34, 0x61, 0xb1, 0xcd, 0xc2, 0x98, 0x47, 0xaa, 0x6c, 0x7a, 0x27, 0x2b, 0x1e, 0xb8, + 0xe4, 0x1e, 0x34, 0xf5, 0x05, 0x80, 0x27, 0x13, 0xde, 0x86, 0x09, 0x4a, 0x24, 0x0d, 0xf4, 0xc5, + 0x80, 0xe7, 0x8a, 0xa4, 0xb7, 0x61, 0x82, 0x12, 0x0d, 0xdc, 0xaf, 0x66, 0xea, 0x95, 0x6e, 0xd5, + 0xac, 0x9f, 0x86, 0x09, 0x13, 0x0d, 0xb9, 0x80, 0xe5, 0xf2, 0x4f, 0x47, 0xe4, 0xc3, 0xcc, 0xf1, + 0x61, 0x65, 0xc2, 0x7d, 0x02, 0x1e, 0x53, 0x3e, 0x85, 0xba, 0xaa, 0x02, 0x2f, 0x55, 0x6e, 0x4e, + 0xfa, 0x76, 0xa4, 0x0d, 0x8d, 0xff, 0x99, 0x86, 0x6e, 0x51, 0xcd, 0xbb, 0x32, 0x61, 0x36, 0x53, + 0xa7, 0x35, 0x59, 0x28, 0x3b, 0x88, 0xf0, 0xb0, 0x19, 0xda, 0x0e, 0x76, 0x01, 0xff, 0xc9, 0xdb, + 0xae, 0xbe, 0x59, 0xf2, 0x3d, 0x58, 0xe6, 0xd5, 0x80, 0x22, 0xbe, 0xed, 0xde, 0x82, 0x86, 0x17, + 0x9d, 0x3d, 0xe5, 0xe9, 0x90, 0xcc, 0xad, 0x1b, 0x66, 0x9d, 0x0b, 0x76, 0x28, 0x53, 0xca, 0xbe, + 0x54, 0xd6, 0xb4, 0xb2, 0x2f, 0x94, 0x0f, 0x61, 0x96, 0x9f, 0x88, 0x54, 0x42, 0xac, 0xd2, 0xb9, + 0x03, 0x8f, 0xc6, 0x83, 0xe0, 0x38, 0x34, 0xa5, 0x96, 0x7c, 0x08, 0x75, 0x59, 0x81, 0xcd, 0x7a, + 0x75, 0x61, 0xd9, 0xd1, 0x37, 0xfd, 0x4c, 0x18, 0xce, 0x89, 0xfa, 0x6c, 0x86, 0xa6, 0x7d, 0x61, + 0xda, 0x98, 0x68, 0xda, 0xe7, 0xa6, 0xeb, 0x70, 0xc7, 0xf6, 0xfd, 0xf0, 0xdc, 0x4a, 0xa2, 0x30, + 0x3c, 0xa6, 0xae, 0x95, 0x84, 0xa3, 0xd8, 0xa1, 0xb8, 0x38, 0x51, 0x95, 0xd9, 0xae, 0x0a, 0xa3, + 0x7d, 0x69, 0xb3, 0x2f, 0x4c, 0xf6, 0xd0, 0x82, 0x7c, 0x95, 0x9f, 0xbf, 0x4d, 0x51, 0xe1, 0xda, + 0x84, 0x31, 0xfa, 0x7f, 0x9e, 0xc3, 0x1b, 0xe3, 0x11, 0x87, 0x07, 0xd6, 0xeb, 0x47, 0x9c, 0xb1, + 0x0e, 0x9d, 0xec, 0x7d, 0xdd, 0x60, 0xb3, 0x18, 0xf9, 0xd5, 0xb7, 0x46, 0xbe, 0x0f, 0x64, 0xfc, + 0xb3, 0x2e, 0x79, 0x98, 0xe1, 0xb0, 0x54, 0x72, 0x33, 0x88, 0x11, 0xff, 0x49, 0x26, 0xe2, 0xa7, + 0x73, 0x9b, 0x50, 0xee, 0xdb, 0x6e, 0x1a, 0xed, 0xff, 0x5d, 0x85, 0x56, 0x56, 0x55, 0x76, 0x2d, + 0x51, 0x8c, 0xe0, 0xea, 0x58, 0x04, 0xeb, 0x38, 0x9c, 0xbe, 0x32, 0x0e, 0x7f, 0x0c, 0xf3, 0xfa, + 0x10, 0x6c, 0x49, 0x87, 0x5a, 0xb9, 0x43, 0x47, 0xdb, 0x1d, 0x08, 0xcf, 0x67, 0xd0, 0x51, 0x27, + 0x66, 0xeb, 0xca, 0x88, 0x6f, 0xe1, 0x41, 0x5a, 0xba, 0x3d, 0x85, 0xf6, 0x71, 0x18, 0x9f, 0xdb, + 0xb1, 0xaa, 0xae, 0x3e, 0xc1, 0x0b, 0xad, 0xa4, 0xd7, 0x23, 0x58, 0xa0, 0x17, 0x11, 0x75, 0x18, + 0x75, 0x2d, 0x31, 0x6f, 0x6c, 0xd7, 0x8d, 0xd5, 0xc4, 0xbd, 0xa1, 0x54, 0x83, 0xe8, 0xec, 0xe9, + 0x3a, 0x57, 0x14, 0xed, 0xfb, 0x68, 0x3f, 0x3b, 0x66, 0xdf, 0x17, 0xf6, 0xc6, 0xef, 0xe7, 0x47, + 0x18, 0xa3, 0xec, 0x7a, 0x23, 0x6c, 0xc4, 0x50, 0x57, 0xb4, 0x4b, 0xc7, 0xea, 0x43, 0xe8, 0x7a, + 0xc1, 0x49, 0x4c, 0x93, 0x44, 0x3e, 0x44, 0xf0, 0xf4, 0x5e, 0x3f, 0x8f, 0xf2, 0x3d, 0x14, 0xf3, + 0xe5, 0x9d, 0x16, 0x2c, 0xf1, 0xca, 0x8d, 0xe6, 0x0c, 0x8d, 0xe7, 0x30, 0x87, 0xb3, 0x9f, 0x2c, + 0x41, 0x8d, 0x5e, 0xf0, 0x33, 0x85, 0x5a, 0x09, 0xe9, 0x05, 0x1b, 0x44, 0x5c, 0x2c, 0x02, 0x3c, + 0x52, 0xf3, 0x8a, 0x13, 0x8e, 0x0c, 0x13, 0x16, 0x4a, 0x2e, 0xde, 0xc9, 0x03, 0x68, 0x7b, 0x49, + 0x68, 0x31, 0x6f, 0x48, 0x13, 0x66, 0x0f, 0x15, 0x56, 0xcb, 0x4b, 0xc2, 0x03, 0x25, 0x23, 0xcb, + 0x50, 0x1b, 0x45, 0xdc, 0x44, 0x40, 0x56, 0x4c, 0x2c, 0x19, 0x11, 0xf4, 0x26, 0x5d, 0xba, 0x5f, + 0x77, 0x96, 0x7c, 0x0c, 0x35, 0x79, 0x6f, 0x8c, 0xd7, 0x57, 0x4b, 0xfa, 0x23, 0x55, 0xee, 0xba, + 0x19, 0x8d, 0x8c, 0x35, 0xe8, 0xe4, 0x35, 0x9c, 0x1b, 0x02, 0x60, 0xe2, 0x86, 0x96, 0xeb, 0x65, + 0xdc, 0xde, 0x6d, 0x7c, 0x2f, 0xe0, 0xf6, 0x55, 0x77, 0xf1, 0xef, 0xb2, 0xfd, 0xbd, 0x63, 0x33, + 0x07, 0x93, 0x6a, 0x7e, 0xf7, 0x65, 0xf0, 0x04, 0x96, 0x4a, 0x2f, 0xdf, 0xc9, 0x1d, 0x80, 0x68, + 0x74, 0xe4, 0x7b, 0x8e, 0x95, 0xae, 0xcb, 0x0d, 0x29, 0xf9, 0x9a, 0x5e, 0xbe, 0xf3, 0xe5, 0x96, + 0xf1, 0x97, 0x55, 0x58, 0x2e, 0x7f, 0xd1, 0xc0, 0xb3, 0x60, 0xb5, 0xa6, 0xaa, 0x2c, 0x58, 0x95, + 0xf5, 0x8e, 0xcb, 0x27, 0x2a, 0x46, 0xac, 0xd8, 0x21, 0xf9, 0xfc, 0xd4, 0x3b, 0xae, 0x50, 0x4e, + 0x6b, 0xa5, 0x98, 0xbc, 0x1c, 0xd5, 0x4e, 0x30, 0x49, 0x93, 0x59, 0x8c, 0x2e, 0x93, 0x75, 0xa8, + 0xf9, 0xf6, 0x11, 0xf5, 0xd5, 0x05, 0xd9, 0x87, 0x57, 0x3e, 0xb9, 0x78, 0xf4, 0x4a, 0xd8, 0xe2, + 0xe7, 0x02, 0xe9, 0xb8, 0xfa, 0x02, 0x9a, 0x19, 0xf1, 0x3b, 0xed, 0x5f, 0x7f, 0x38, 0xde, 0x13, + 0x38, 0x70, 0xff, 0xd7, 0x9e, 0x30, 0x5e, 0xcb, 0x85, 0xaa, 0xf0, 0x76, 0xe5, 0x87, 0x82, 0xfb, + 0xbe, 0xec, 0x76, 0x61, 0xb1, 0xec, 0x2b, 0xe6, 0x35, 0x00, 0xfb, 0x45, 0xc0, 0x7e, 0x39, 0xe0, + 0xb5, 0x19, 0x4e, 0x00, 0xdc, 0x82, 0x4e, 0xfe, 0xfd, 0x4a, 0xc9, 0xa7, 0x91, 0x99, 0x28, 0x0c, + 0x7d, 0x9c, 0xa0, 0xf3, 0xc5, 0x17, 0x2b, 0x42, 0x69, 0xdc, 0x4f, 0x61, 0x26, 0x7c, 0xf4, 0xf8, + 0x25, 0xd4, 0x95, 0x85, 0x38, 0x64, 0x78, 0xae, 0xbe, 0x31, 0xe7, 0xbf, 0xc9, 0x5d, 0x80, 0xa1, + 0x9d, 0x7c, 0x37, 0xa2, 0xb1, 0x8d, 0xc7, 0x8f, 0xba, 0x99, 0x91, 0xc8, 0x56, 0x78, 0x91, 0x35, + 0xe4, 0xa7, 0x13, 0x1d, 0xf2, 0x5e, 0xf4, 0x9a, 0x9f, 0x64, 0xee, 0x00, 0x9c, 0x5d, 0xf8, 0x76, + 0x20, 0xb5, 0x32, 0xe8, 0x1b, 0x42, 0xc2, 0xd5, 0xc6, 0x9f, 0x55, 0xa0, 0x9d, 0xfb, 0xba, 0x4f, + 0xde, 0x83, 0x96, 0x40, 0xa3, 0x81, 0x7d, 0xe4, 0x53, 0xc9, 0xb3, 0x6e, 0x36, 0xb9, 0x6c, 0x4b, + 0x8a, 0xf8, 0x0e, 0x20, 0x31, 0x95, 0x8d, 0xe4, 0xd4, 0x12, 0x42, 0x65, 0xb4, 0x06, 0xdd, 0x9c, + 0x91, 0x75, 0xd6, 0xc7, 0xbb, 0xf4, 0x4e, 0xd6, 0xee, 0xb0, 0x6f, 0xfc, 0x4b, 0x05, 0x16, 0xcb, + 0x5e, 0xe7, 0x90, 0x0f, 0x32, 0x6b, 0xd6, 0xcd, 0xd2, 0x5b, 0x00, 0x5c, 0x2b, 0x7f, 0xaa, 0xe7, + 0xae, 0x3c, 0xda, 0x7e, 0x70, 0xc5, 0x9b, 0x9f, 0x1f, 0x7a, 0xe6, 0xfe, 0xb4, 0x48, 0x1e, 0x47, + 0xf9, 0xba, 0xe4, 0x8d, 0x4d, 0xe8, 0x16, 0xe5, 0xf9, 0xaf, 0x20, 0x95, 0xe2, 0x57, 0x90, 0xb2, + 0x4f, 0x28, 0xff, 0x5c, 0x81, 0xf9, 0xc2, 0xf3, 0x21, 0x62, 0x64, 0x28, 0x90, 0xe2, 0xeb, 0x20, + 0xec, 0xba, 0xcf, 0x0a, 0x5d, 0x67, 0x94, 0x3f, 0x45, 0xfa, 0xa1, 0x7b, 0xed, 0x59, 0x86, 0x2d, + 0x76, 0xd8, 0x35, 0xd8, 0x1a, 0xef, 0x41, 0x33, 0x23, 0x2a, 0xfd, 0x0a, 0x77, 0x00, 0x20, 0x5f, + 0x01, 0x1d, 0xe0, 0xa1, 0x9d, 0x47, 0x2e, 0x46, 0xb1, 0xf8, 0x2d, 0x58, 0xf1, 0x08, 0xc4, 0xb0, + 0x95, 0x05, 0xde, 0xe5, 0xfa, 0xcb, 0xb2, 0xfa, 0xe8, 0xa3, 0x05, 0xc6, 0x3f, 0xcc, 0x40, 0x33, + 0xf3, 0x2e, 0x8a, 0xbc, 0x9f, 0xb9, 0x20, 0x48, 0x77, 0x39, 0x61, 0x91, 0x7e, 0x8e, 0x25, 0x9f, + 0xf2, 0xb9, 0x24, 0x1f, 0xb7, 0x09, 0x6b, 0xb9, 0x27, 0xde, 0xd0, 0x0b, 0x05, 0x9f, 0xf2, 0xc2, + 0x1c, 0xbc, 0x48, 0xfd, 0xe6, 0xdd, 0xe8, 0x26, 0x4c, 0x9d, 0x41, 0xdd, 0x84, 0x11, 0x03, 0xda, + 0xe2, 0x86, 0x34, 0x74, 0xe5, 0xad, 0x1d, 0x4e, 0xe3, 0xa6, 0x9b, 0xb0, 0x9d, 0xd0, 0x15, 0x97, + 0x74, 0xe4, 0x2e, 0x34, 0xb5, 0x8d, 0x17, 0xa9, 0x2f, 0x67, 0x68, 0x31, 0x88, 0xf8, 0x29, 0x20, + 0xb1, 0x87, 0xd4, 0x4a, 0x46, 0x47, 0x01, 0x65, 0xe2, 0x8b, 0x7e, 0xdd, 0x04, 0x2e, 0xda, 0x17, + 0x12, 0x3e, 0xef, 0x79, 0x7e, 0x1e, 0x8e, 0xd8, 0x49, 0xe8, 0x05, 0x27, 0xe2, 0xeb, 0x49, 0xdd, + 0x6c, 0x06, 0x36, 0xdb, 0x45, 0x11, 0x79, 0x08, 0x1d, 0x3f, 0x74, 0x6c, 0xdf, 0x52, 0x77, 0x03, + 0xe2, 0xf3, 0x49, 0xdd, 0x6c, 0x0b, 0xa9, 0xca, 0x26, 0xc8, 0x13, 0x68, 0x32, 0x31, 0x02, 0xb2, + 0xd1, 0xf2, 0x95, 0xaa, 0x6a, 0x74, 0x3a, 0x36, 0x26, 0xb0, 0x74, 0x9c, 0xfa, 0x3a, 0x0c, 0xe5, + 0x31, 0xf2, 0xee, 0xf8, 0x5b, 0xb4, 0xb2, 0x10, 0xcc, 0xed, 0xe8, 0xad, 0xc2, 0x8e, 0xfe, 0x18, + 0x16, 0xd3, 0xa7, 0x06, 0x99, 0xc4, 0xa5, 0x2d, 0xaf, 0x4a, 0xb5, 0x6e, 0x4f, 0x65, 0x30, 0xdf, + 0x27, 0xa0, 0xef, 0x61, 0x7c, 0x60, 0x30, 0xe3, 0x20, 0x56, 0xf5, 0x20, 0x1a, 0xff, 0x55, 0x81, + 0x95, 0x89, 0x0f, 0xdd, 0x44, 0x24, 0xf3, 0x05, 0x5a, 0x45, 0x32, 0x5f, 0xba, 0xf1, 0x32, 0xa2, + 0x9a, 0x5e, 0x46, 0xe4, 0x76, 0xd4, 0xe9, 0x42, 0xe6, 0xb3, 0x06, 0xdd, 0xc8, 0x8e, 0x69, 0xc0, + 0x2c, 0x97, 0x8a, 0xcb, 0x54, 0x2f, 0xc2, 0x40, 0xe9, 0x48, 0xf9, 0xa6, 0x10, 0xcb, 0x7c, 0x7f, + 0x68, 0x3b, 0x7c, 0x41, 0x96, 0x61, 0x32, 0x3b, 0xb4, 0x9d, 0xc3, 0x7e, 0x7e, 0x37, 0xac, 0x15, + 0x52, 0xa7, 0x1f, 0x01, 0x29, 0xa2, 0x9f, 0xf5, 0x45, 0x18, 0x35, 0xcc, 0x6e, 0x1e, 0xff, 0xac, + 0x6f, 0x7c, 0x52, 0xda, 0x56, 0xec, 0x9b, 0x92, 0xb6, 0x1a, 0xbf, 0xae, 0xc0, 0xcd, 0x09, 0xcf, + 0xed, 0xae, 0xdc, 0xc1, 0xf3, 0x29, 0x69, 0xb5, 0x98, 0x92, 0x3e, 0x82, 0x05, 0x2f, 0x60, 0x34, + 0x3e, 0xb6, 0x25, 0xe3, 0x5c, 0xd7, 0xdd, 0xd0, 0x2a, 0x75, 0x1a, 0x34, 0x9e, 0x95, 0xb0, 0x78, + 0x7b, 0x1e, 0x61, 0xfc, 0x75, 0x05, 0x56, 0x26, 0x3e, 0x2c, 0xbb, 0x92, 0xbf, 0x01, 0xed, 0x94, + 0x3f, 0x1f, 0x11, 0xd9, 0x84, 0xa6, 0x6e, 0xc2, 0x61, 0x7f, 0xac, 0x11, 0xfd, 0x89, 0x8d, 0x90, + 0x89, 0xcb, 0xf3, 0x52, 0x32, 0xd7, 0x68, 0xc6, 0xbf, 0x56, 0x60, 0xa9, 0xf4, 0xe1, 0x20, 0x79, + 0x02, 0x4b, 0xea, 0x8a, 0xde, 0xf1, 0x47, 0x09, 0xa3, 0xb1, 0xc5, 0x53, 0x13, 0x75, 0xc5, 0xbc, + 0x80, 0xca, 0x0d, 0xa9, 0xdb, 0xe0, 0x2a, 0xf2, 0x34, 0x7d, 0x43, 0x4b, 0x2f, 0x18, 0x8d, 0x03, + 0xdb, 0x47, 0xa7, 0x2a, 0x7e, 0x42, 0x96, 0xda, 0x2d, 0x54, 0x4a, 0xaf, 0x9f, 0xc0, 0xaa, 0xf2, + 0xe2, 0x8b, 0xc9, 0x91, 0xed, 0xdb, 0x81, 0xa3, 0xab, 0x93, 0x27, 0xdc, 0x1e, 0x5a, 0xbc, 0xca, + 0x18, 0x08, 0x6f, 0xe3, 0xdf, 0x2a, 0xd0, 0xce, 0xbd, 0x36, 0x2c, 0x3d, 0x65, 0xe7, 0x76, 0xd7, + 0x6a, 0xc9, 0xee, 0xaa, 0x5f, 0xdd, 0x34, 0x70, 0x21, 0xbf, 0x03, 0xa0, 0xda, 0xad, 0x67, 0x55, + 0x03, 0x25, 0x83, 0x88, 0x9f, 0xc5, 0x73, 0x64, 0xf5, 0x02, 0xdc, 0xc9, 0x8a, 0x07, 0x11, 0x5f, + 0x64, 0x75, 0x5f, 0x78, 0x91, 0xba, 0x12, 0x6c, 0x2a, 0xd9, 0x20, 0xe2, 0xa7, 0xd0, 0x76, 0xee, + 0xc1, 0xe3, 0xbb, 0xb7, 0xe0, 0xa3, 0x35, 0x68, 0xe8, 0xf3, 0x16, 0x99, 0x83, 0xe9, 0xf5, 0x9d, + 0x9f, 0x75, 0xa7, 0x48, 0x1d, 0x66, 0x06, 0x7b, 0x87, 0x4f, 0xbb, 0x33, 0xf8, 0xab, 0xdf, 0xad, + 0x7d, 0xf4, 0x57, 0x15, 0x68, 0xe8, 0x4d, 0x8b, 0xb4, 0xa1, 0xb1, 0x31, 0xd8, 0x34, 0xad, 0xc1, + 0xce, 0x17, 0xbb, 0xdd, 0x29, 0xb2, 0x00, 0xf3, 0xe6, 0xd6, 0xeb, 0xdd, 0x83, 0x2d, 0xeb, 0xdb, + 0x5d, 0xf3, 0xeb, 0x57, 0xbb, 0xeb, 0x9b, 0xdd, 0x0a, 0x99, 0x87, 0x26, 0x0a, 0xb7, 0x77, 0xf7, + 0x0f, 0xba, 0x55, 0x42, 0xa0, 0xf3, 0x6a, 0x77, 0x63, 0xfd, 0x55, 0x6a, 0x34, 0x4d, 0x3a, 0x00, + 0x52, 0x26, 0x6c, 0x66, 0xc8, 0x0d, 0x68, 0xa3, 0xd3, 0xc1, 0x37, 0x3b, 0x3b, 0x5b, 0xaf, 0xba, + 0xb3, 0xa4, 0x0b, 0x2d, 0x69, 0x82, 0x92, 0xda, 0x47, 0x2f, 0x00, 0xd2, 0x1d, 0x91, 0x73, 0xdc, + 0xd9, 0xdd, 0xd9, 0xea, 0x4e, 0x91, 0x16, 0xd4, 0x77, 0x76, 0xad, 0xad, 0x9d, 0x8d, 0xf5, 0xbd, + 0x6e, 0x85, 0x34, 0x60, 0x56, 0xac, 0x2c, 0xdd, 0xaa, 0x6c, 0xc6, 0x60, 0xaf, 0x3b, 0xfd, 0xe4, + 0x73, 0x00, 0xf9, 0x7c, 0x44, 0xfc, 0xeb, 0xcd, 0x63, 0x98, 0x11, 0x7f, 0x55, 0x12, 0x91, 0xf9, + 0xcf, 0x9f, 0x55, 0x25, 0xcb, 0xfc, 0xf7, 0xcf, 0xe3, 0xca, 0xcb, 0xb9, 0x9f, 0xcf, 0x8a, 0x6f, + 0xeb, 0x47, 0x35, 0xf1, 0xe7, 0xd3, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x80, 0x4d, 0x63, 0x82, + 0x4b, 0x34, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/calico-vpp-agent/proto/felixbackend.proto b/calico-vpp-agent/proto/felixbackend.proto index d166d91bb..24dddbb84 100644 --- a/calico-vpp-agent/proto/felixbackend.proto +++ b/calico-vpp-agent/proto/felixbackend.proto @@ -87,6 +87,11 @@ message ToDataplane { // HostIPRemove is sent when a host IP is removed. HostMetadataRemove host_metadata_remove = 18; + // HostMetadataV4V6Update is sent when a host is added or updated. + HostMetadataV4V6Update host_metadata_v4v6_update = 37; + // HostIPRemove is sent when a host is removed. + HostMetadataV4V6Remove host_metadata_v4v6_remove = 38; + // IPAMPoolUpdate is sent when an IPAM pool is added/updated. IPAMPoolUpdate ipam_pool_update = 16; // IPAMPoolRemove is sent when an IPAM pool is removed. @@ -462,6 +467,19 @@ message WireguardStatusUpdate { IPVersion ip_version = 2; } +message HostMetadataV4V6Update { + string hostname = 1; + string ipv4_addr = 2; + string ipv6_addr = 3; + string asnumber = 4; + map labels = 5; +} + +message HostMetadataV4V6Remove { + string hostname = 1; + string ipv4_addr = 2; +} + message HostMetadataUpdate { string hostname = 1; string ipv4_addr = 2;