From 4d637050ba7971f1be82a0275dfe3b2c84241ed9 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Tue, 31 Dec 2024 12:31:30 -0800 Subject: [PATCH 1/5] Program connected routes for VXLAN tunnel addresses --- felix/dataplane/linux/vxlan_mgr.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/felix/dataplane/linux/vxlan_mgr.go b/felix/dataplane/linux/vxlan_mgr.go index e0d8285365c..adca4f263a2 100644 --- a/felix/dataplane/linux/vxlan_mgr.go +++ b/felix/dataplane/linux/vxlan_mgr.go @@ -198,6 +198,15 @@ func (m *vxlanManager) OnUpdate(protoBufMsg interface{}) { m.routesDirty = true } + // Process routes for remote tunnel endpoints as well. This is necessary to ensure hosts can + // communicate with tunnel endpoints that whose IP address has been borrowed. + // TODO: We only need to program these if they aren't masked by a block route. Who should be responsible for that? + if msg.Type == proto.RouteType_REMOTE_TUNNEL && msg.IpPoolType == proto.IPPoolType_VXLAN { + m.logCtx.WithField("msg", msg).Debug("VXLAN data plane received route update for VXLAN tunnel") + m.routesByDest[msg.Dst] = msg + m.routesDirty = true + } + // Process IPAM blocks that aren't associated to a single or /32 local workload if routeIsLocalVXLANBlock(msg) { m.logCtx.WithField("msg", msg).Debug("VXLAN data plane received route update for IPAM block") @@ -491,23 +500,27 @@ func (m *vxlanManager) noEncapRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routeta } func (m *vxlanManager) tunneledRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routetable.Target { + if r.Type == proto.RouteType_REMOTE_TUNNEL { + // We treat remote tunnel routes as directly connected. They don't have a gateway of + // the VTEP because they ARE the VTEP! + return &routetable.Target{CIDR: cidr} + } + // Extract the gateway addr for this route based on its remote VTEP. vtep, ok := m.vtepsByNode[r.DstNodeName] if !ok { // When the VTEP arrives, it'll set routesDirty=true so this loop will execute again. return nil } - vtepAddr := vtep.Ipv4Addr if m.ipVersion == 6 { vtepAddr = vtep.Ipv6Addr } - vxlanRoute := routetable.Target{ + return &routetable.Target{ Type: routetable.TargetTypeVXLAN, CIDR: cidr, GW: ip.FromString(vtepAddr), } - return &vxlanRoute } func (m *vxlanManager) OnParentNameUpdate(name string) { From dcdaf147e57636a414faa9e326b3a4638adead1a Mon Sep 17 00:00:00 2001 From: Shaun Crampton Date: Thu, 2 Jan 2025 17:56:13 +0000 Subject: [PATCH 2/5] Calculate which routes are borrowed in route resolver. Add new Borrowed flag to protobuf so dataplane can tell which routes are borrowed. --- felix/calc/l3_route_resolver.go | 13 ++ felix/calc/states_for_test.go | 7 ++ felix/proto/felixbackend.pb.go | 214 +++++++++++++++++--------------- felix/proto/felixbackend.proto | 1 + 4 files changed, 133 insertions(+), 102 deletions(-) diff --git a/felix/calc/l3_route_resolver.go b/felix/calc/l3_route_resolver.go index e4e54506bd9..eed77488d3d 100644 --- a/felix/calc/l3_route_resolver.go +++ b/felix/calc/l3_route_resolver.go @@ -747,6 +747,8 @@ func (c *L3RouteResolver) flush() { Dst: cidr.String(), } poolAllowsCrossSubnet := false + var blockSeen bool + var blockNodeName string for _, entry := range buf { ri := entry.Data.(RouteInfo) if len(ri.Pools) > 0 { @@ -766,6 +768,13 @@ func (c *L3RouteResolver) flush() { } if len(ri.Blocks) > 0 { // We only expect one Block entry for any given CIDR. This constraint is upheld by the datastore. + if blockSeen && blockNodeName != ri.Blocks[0].NodeName { + logCxt.Debug("Borrowed block IP") + rt.Borrowed = true + } else { + blockSeen = true + blockNodeName = ri.Blocks[0].NodeName + } rt.DstNodeName = ri.Blocks[0].NodeName if rt.DstNodeName == c.myNodeName { logCxt.Debug("Local workload route.") @@ -794,6 +803,10 @@ func (c *L3RouteResolver) flush() { // multiple workload, or workload and tunnel, or multiple node Refs with the same IP. Since this will be // transient, we can always just use the first entry (and related tunnel entries) rt.DstNodeName = ri.Refs[0].NodeName + if blockSeen && blockNodeName != rt.DstNodeName { + logCxt.Debug("Borrowed ref IP") + rt.Borrowed = true + } if ri.Refs[0].RefType == RefTypeWEP { // This is not a tunnel ref, so must be a workload. if ri.Refs[0].NodeName == c.myNodeName { diff --git a/felix/calc/states_for_test.go b/felix/calc/states_for_test.go index cd36dc3cd70..31384edd86c 100644 --- a/felix/calc/states_for_test.go +++ b/felix/calc/states_for_test.go @@ -1661,6 +1661,7 @@ var vxlanWithBlockAndBorrows = vxlanWithBlock.withKVUpdates( DstNodeName: remoteHostname2, DstNodeIp: remoteHost2IP.String(), NatOutgoing: true, + Borrowed: true, }, ) @@ -1731,6 +1732,7 @@ var vxlanBlockOwnerSwitch = vxlanWithBlockAndBorrows.withKVUpdates( DstNodeName: remoteHostname, DstNodeIp: remoteHostIP.String(), NatOutgoing: true, + Borrowed: true, }, ).withName("VXLAN owner switch") @@ -1784,6 +1786,7 @@ var vxlanLocalBlockWithBorrows = empty.withKVUpdates( DstNodeName: remoteHostname, DstNodeIp: remoteHostIP.String(), NatOutgoing: true, + Borrowed: true, }, ).withExpectedEncapsulation( &proto.Encapsulation{IpipEnabled: false, VxlanEnabled: true, VxlanEnabledV6: false}, @@ -1807,6 +1810,7 @@ var localVXLANWep1Route2 = types.RouteUpdate{ DstNodeIp: localHostIP.String(), NatOutgoing: true, LocalWorkload: true, + Borrowed: true, } // As vxlanLocalBlockWithBorrows but with a local workload. The local workload has an IP that overlaps with @@ -1905,6 +1909,7 @@ var vxlanLocalBlockWithBorrowsCrossSubnetNodeRes = vxlanLocalBlockWithBorrowsNod DstNodeName: remoteHostname, DstNodeIp: remoteHostIP.String(), SameSubnet: true, // cross subnet. + Borrowed: true, }, ).withName("VXLAN local with borrows cross subnet (node resources)") @@ -1961,6 +1966,7 @@ var vxlanLocalBlockWithBorrowsDifferentSubnetNodeRes = vxlanLocalBlockWithBorrow DstNodeName: remoteHostname, DstNodeIp: remoteHostIP.String(), SameSubnet: false, // subnets don't match. + Borrowed: true, }, ).withName("VXLAN cross subnet different subnet (node resources)") @@ -1992,6 +1998,7 @@ var vxlanWithBlockAndBorrowsAndMissingFirstVTEP = vxlanWithBlockAndBorrows.withK DstNodeName: remoteHostname2, DstNodeIp: remoteHost2IP.String(), NatOutgoing: true, + Borrowed: true, }, ) diff --git a/felix/proto/felixbackend.pb.go b/felix/proto/felixbackend.pb.go index 53a93bbd750..5502bfe59e6 100644 --- a/felix/proto/felixbackend.pb.go +++ b/felix/proto/felixbackend.pb.go @@ -4666,6 +4666,7 @@ type RouteUpdate struct { 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"` + Borrowed bool `protobuf:"varint,11,opt,name=borrowed,proto3" json:"borrowed,omitempty"` } func (x *RouteUpdate) Reset() { @@ -4763,6 +4764,13 @@ func (x *RouteUpdate) GetTunnelType() *TunnelType { return nil } +func (x *RouteUpdate) GetBorrowed() bool { + if x != nil { + return x.Borrowed + } + return false +} + type RouteRemove struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6283,7 +6291,7 @@ var file_felixbackend_proto_rawDesc = []byte{ 0x76, 0x78, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x78, 0x6c, 0x61, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x22, 0xdd, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x22, 0xf9, 0x02, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0c, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x6f, @@ -6305,108 +6313,110 @@ var file_felixbackend_proto_rawDesc = []byte{ 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x1f, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x64, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, - 0x74, 0x22, 0xea, 0x01, 0x0a, 0x19, 0x56, 0x58, 0x4c, 0x41, 0x4e, 0x54, 0x75, 0x6e, 0x6e, 0x65, - 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6d, 0x61, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x76, 0x34, 0x41, 0x64, - 0x64, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x70, 0x12, 0x15, 0x0a, 0x06, - 0x6d, 0x61, 0x63, 0x5f, 0x76, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, - 0x63, 0x56, 0x36, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x76, 0x36, 0x41, 0x64, 0x64, 0x72, - 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x70, 0x76, 0x36, 0x22, 0x2f, + 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x62, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x65, 0x64, 0x22, 0x1f, 0x0a, 0x0b, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x64, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x73, 0x74, 0x22, 0xea, 0x01, 0x0a, 0x19, 0x56, 0x58, 0x4c, 0x41, 0x4e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, - 0x84, 0x01, 0x0a, 0x17, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x70, - 0x76, 0x34, 0x41, 0x64, 0x64, 0x72, 0x22, 0x35, 0x0a, 0x17, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8b, 0x01, - 0x0a, 0x19, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x56, 0x36, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, - 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x56, 0x36, 0x12, 0x2e, 0x0a, 0x13, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x49, 0x70, 0x76, 0x36, 0x41, 0x64, 0x64, 0x72, 0x22, 0x37, 0x0a, 0x19, 0x57, - 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x56, 0x36, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, - 0x47, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, - 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x69, 0x64, - 0x72, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x14, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x43, 0x69, 0x64, 0x72, 0x73, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, - 0x5f, 0x63, 0x69, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x72, 0x43, 0x69, 0x64, 0x72, 0x73, 0x22, 0x59, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, - 0x74, 0x22, 0xec, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x70, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x6f, - 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x72, 0x49, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x69, 0x70, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x49, 0x70, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, - 0x22, 0x41, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x2a, 0x28, 0x0a, 0x09, 0x49, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, - 0x34, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, 0x36, 0x10, 0x06, 0x2a, 0x89, 0x01, - 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, - 0x49, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, - 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01, 0x12, - 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x02, - 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x4c, 0x4f, - 0x41, 0x44, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x48, 0x4f, - 0x53, 0x54, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x54, - 0x55, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x41, 0x4c, - 0x5f, 0x54, 0x55, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x06, 0x2a, 0x39, 0x0a, 0x0a, 0x49, 0x50, 0x50, - 0x6f, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, - 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x5f, 0x45, 0x4e, 0x43, 0x41, 0x50, 0x10, 0x01, 0x12, - 0x09, 0x0a, 0x05, 0x56, 0x58, 0x4c, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, - 0x49, 0x50, 0x10, 0x03, 0x32, 0x3e, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x79, - 0x6e, 0x63, 0x12, 0x30, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x66, 0x65, 0x6c, - 0x69, 0x78, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, - 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x54, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, + 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x76, 0x34, 0x41, 0x64, 0x64, 0x72, 0x12, 0x28, + 0x0a, 0x10, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x61, 0x63, 0x5f, + 0x76, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x63, 0x56, 0x36, 0x12, + 0x1b, 0x0a, 0x09, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x76, 0x36, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2c, 0x0a, 0x12, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x70, + 0x76, 0x36, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x70, 0x76, 0x36, 0x22, 0x2f, 0x0a, 0x19, 0x56, 0x58, + 0x4c, 0x41, 0x4e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x17, + 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, + 0x69, 0x70, 0x76, 0x34, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x70, 0x76, 0x34, 0x41, 0x64, + 0x64, 0x72, 0x22, 0x35, 0x0a, 0x17, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x19, 0x57, 0x69, + 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x56, + 0x36, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x5f, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x56, 0x36, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, + 0x70, 0x76, 0x36, 0x41, 0x64, 0x64, 0x72, 0x22, 0x37, 0x0a, 0x19, 0x57, 0x69, 0x72, 0x65, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x56, 0x36, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x47, 0x50, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x69, + 0x64, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x69, 0x64, 0x72, 0x73, 0x12, 0x34, + 0x0a, 0x16, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, + 0x69, 0x64, 0x72, 0x73, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x64, + 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x43, 0x69, 0x64, + 0x72, 0x73, 0x22, 0x59, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, + 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xec, 0x01, + 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x5f, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x49, 0x70, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x70, 0x12, + 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, + 0x70, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x41, 0x0a, 0x0d, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2a, + 0x28, 0x0a, 0x09, 0x49, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x07, 0x0a, 0x03, + 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, 0x34, 0x10, 0x04, 0x12, + 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, 0x36, 0x10, 0x06, 0x2a, 0x89, 0x01, 0x0a, 0x09, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x49, 0x44, 0x52, 0x5f, + 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, + 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, + 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, + 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x03, + 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x04, + 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x54, 0x55, 0x4e, 0x4e, 0x45, + 0x4c, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x54, 0x55, 0x4e, + 0x4e, 0x45, 0x4c, 0x10, 0x06, 0x2a, 0x39, 0x0a, 0x0a, 0x49, 0x50, 0x50, 0x6f, 0x6f, 0x6c, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0c, 0x0a, + 0x08, 0x4e, 0x4f, 0x5f, 0x45, 0x4e, 0x43, 0x41, 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x56, + 0x58, 0x4c, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x49, 0x50, 0x10, 0x03, + 0x32, 0x3e, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x30, + 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x66, 0x65, 0x6c, 0x69, 0x78, 0x2e, 0x53, + 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x66, 0x65, 0x6c, + 0x69, 0x78, 0x2e, 0x54, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x30, 0x01, + 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/felix/proto/felixbackend.proto b/felix/proto/felixbackend.proto index c72b4c3194f..87f2b551dbf 100644 --- a/felix/proto/felixbackend.proto +++ b/felix/proto/felixbackend.proto @@ -601,6 +601,7 @@ message RouteUpdate { bool nat_outgoing = 8; bool local_workload = 9; TunnelType tunnel_type = 10; + bool borrowed = 11; } message RouteRemove { From 56f62ef4f7eeec167c8f149e7ef8ff28dcc09976 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Thu, 2 Jan 2025 10:33:47 -0800 Subject: [PATCH 3/5] Only program routes for borrowed tunnel IPs --- felix/dataplane/linux/vxlan_mgr.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/felix/dataplane/linux/vxlan_mgr.go b/felix/dataplane/linux/vxlan_mgr.go index adca4f263a2..997b4cfcca9 100644 --- a/felix/dataplane/linux/vxlan_mgr.go +++ b/felix/dataplane/linux/vxlan_mgr.go @@ -200,9 +200,8 @@ func (m *vxlanManager) OnUpdate(protoBufMsg interface{}) { // Process routes for remote tunnel endpoints as well. This is necessary to ensure hosts can // communicate with tunnel endpoints that whose IP address has been borrowed. - // TODO: We only need to program these if they aren't masked by a block route. Who should be responsible for that? - if msg.Type == proto.RouteType_REMOTE_TUNNEL && msg.IpPoolType == proto.IPPoolType_VXLAN { - m.logCtx.WithField("msg", msg).Debug("VXLAN data plane received route update for VXLAN tunnel") + if msg.Type == proto.RouteType_REMOTE_TUNNEL && msg.IpPoolType == proto.IPPoolType_VXLAN && msg.Borrowed { + m.logCtx.WithField("msg", msg).Debug("VXLAN data plane received route update for borrowed VXLAN tunnel IP") m.routesByDest[msg.Dst] = msg m.routesDirty = true } From eb6744f03dc6564e6c129c999f31cfa6b8548a40 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Thu, 2 Jan 2025 11:39:49 -0800 Subject: [PATCH 4/5] Fix static checks --- felix/types/update.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/felix/types/update.go b/felix/types/update.go index 83436898a65..66d4f2c363b 100644 --- a/felix/types/update.go +++ b/felix/types/update.go @@ -54,6 +54,7 @@ type RouteUpdate struct { NatOutgoing bool LocalWorkload bool TunnelType *proto.TunnelType + Borrowed bool } func ProtoToVXLANTunnelEndpointUpdate(msg *proto.VXLANTunnelEndpointUpdate) VXLANTunnelEndpointUpdate { @@ -95,5 +96,6 @@ func ProtoToRouteUpdate(msg *proto.RouteUpdate) RouteUpdate { NatOutgoing: msg.NatOutgoing, LocalWorkload: msg.LocalWorkload, TunnelType: msg.TunnelType, + Borrowed: msg.Borrowed, } } From 87f08524c9fd01d22e1676ee9e8a62a0e87f098f Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Thu, 2 Jan 2025 13:50:36 -0800 Subject: [PATCH 5/5] Add some UT --- felix/dataplane/linux/vxlan_mgr_test.go | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/felix/dataplane/linux/vxlan_mgr_test.go b/felix/dataplane/linux/vxlan_mgr_test.go index 2145ddf935b..670d91c6173 100644 --- a/felix/dataplane/linux/vxlan_mgr_test.go +++ b/felix/dataplane/linux/vxlan_mgr_test.go @@ -461,4 +461,64 @@ var _ = Describe("VXLANManager", func() { Expect(rt.currentRoutes["eth0"]).To(HaveLen(1)) Expect(rt.currentRoutes[dataplanedefs.VXLANIfaceNameV6]).To(HaveLen(0)) }) + + It("should program directly connected routes for remote VTEPs with borrowed IP addresses", func() { + By("Sending a borrowed tunnel IP address") + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_REMOTE_TUNNEL, + IpPoolType: proto.IPPoolType_VXLAN, + Dst: "10.0.1.1/32", + DstNodeName: "node2", + DstNodeIp: "172.16.0.1", + Borrowed: true, + }) + + err := manager.CompleteDeferredWork() + Expect(err).NotTo(HaveOccurred()) + + // Expect a directly connected route to the borrowed IP. + Expect(rt.currentRoutes[dataplanedefs.VXLANIfaceNameV4]).To(HaveLen(1)) + Expect(rt.currentRoutes[dataplanedefs.VXLANIfaceNameV4][0]).To(Equal(routetable.Target{CIDR: ip.MustParseCIDROrIP("10.0.1.1/32")})) + + // Delete the route. + manager.OnUpdate(&proto.RouteRemove{ + Dst: "10.0.1.1/32", + }) + + err = manager.CompleteDeferredWork() + Expect(err).NotTo(HaveOccurred()) + + // Expect no routes. + Expect(rt.currentRoutes["vxlan.calico"]).To(HaveLen(0)) + }) + + It("IPv6: should program directly connected routes for remote VTEPs with borrowed IP addresses", func() { + By("Sending a borrowed tunnel IP address") + managerV6.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_REMOTE_TUNNEL, + IpPoolType: proto.IPPoolType_VXLAN, + Dst: "fc00:10:244::1/112", + DstNodeName: "node2", + DstNodeIp: "fc00:10:10::8", + Borrowed: true, + }) + + err := managerV6.CompleteDeferredWork() + Expect(err).NotTo(HaveOccurred()) + + // Expect a directly connected route to the borrowed IP. + Expect(rt.currentRoutes[dataplanedefs.VXLANIfaceNameV6]).To(HaveLen(1)) + Expect(rt.currentRoutes[dataplanedefs.VXLANIfaceNameV6][0]).To(Equal(routetable.Target{CIDR: ip.MustParseCIDROrIP("fc00:10:244::1/112")})) + + // Delete the route. + managerV6.OnUpdate(&proto.RouteRemove{ + Dst: "fc00:10:244::1/112", + }) + + err = managerV6.CompleteDeferredWork() + Expect(err).NotTo(HaveOccurred()) + + // Expect no routes. + Expect(rt.currentRoutes["vxlan.calico"]).To(HaveLen(0)) + }) })