Skip to content

Commit 016f52a

Browse files
authored
vpc egress gateway: drop traffic if no nexthop is available (#5370)
Signed-off-by: zhangzujian <zhangzujian.7@gmail.com>
1 parent 5e4e20a commit 016f52a

File tree

2 files changed

+88
-48
lines changed

2 files changed

+88
-48
lines changed

pkg/controller/vpc_egress_gateway.go

Lines changed: 86 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -135,56 +135,55 @@ func (c *Controller) handleAddOrUpdateVpcEgressGateway(key string) error {
135135
gw.Status.Workload.Nodes = nil
136136
nodeNexthopIPv4 := make(map[string]string, int(gw.Spec.Replicas))
137137
nodeNexthopIPv6 := make(map[string]string, int(gw.Spec.Replicas))
138-
if !util.DeploymentIsReady(deploy) {
138+
ready := util.DeploymentIsReady(deploy)
139+
if !ready {
139140
gw.Status.Ready = false
140141
msg := fmt.Sprintf("Waiting for %s %s to be ready", deploy.Kind, deploy.Name)
141142
gw.Status.Conditions.SetCondition(kubeovnv1.Ready, corev1.ConditionFalse, "Processing", msg, gw.Generation)
142-
} else {
143-
// get the pods of the deployment to collect the pod IPs
144-
podSelector, err := metav1.LabelSelectorAsSelector(deploy.Spec.Selector)
145-
if err != nil {
146-
err = fmt.Errorf("failed to get pod selector of deployment %s/%s: %w", deploy.Namespace, deploy.Name, err)
147-
klog.Error(err)
148-
return err
149-
}
143+
}
144+
// get the pods of the deployment to collect the pod IPs
145+
podSelector, err := metav1.LabelSelectorAsSelector(deploy.Spec.Selector)
146+
if err != nil {
147+
err = fmt.Errorf("failed to get pod selector of deployment %s/%s: %w", deploy.Namespace, deploy.Name, err)
148+
klog.Error(err)
149+
return err
150+
}
151+
152+
pods, err := c.podsLister.Pods(deploy.Namespace).List(podSelector)
153+
if err != nil {
154+
err = fmt.Errorf("failed to list pods of deployment %s/%s: %w", deploy.Namespace, deploy.Name, err)
155+
klog.Error(err)
156+
return err
157+
}
150158

151-
pods, err := c.podsLister.Pods(deploy.Namespace).List(podSelector)
159+
// update gateway status including the internal/external IPs and the nodes where the pods are running
160+
gw.Status.Workload.Nodes = make([]string, 0, len(pods))
161+
for _, pod := range pods {
162+
if len(pod.Status.PodIPs) == 0 {
163+
continue
164+
}
165+
extIPs, err := util.PodAttachmentIPs(pod, attachmentNetworkName)
152166
if err != nil {
153-
err = fmt.Errorf("failed to list pods of deployment %s/%s: %w", deploy.Namespace, deploy.Name, err)
154167
klog.Error(err)
155-
return err
168+
continue
156169
}
157170

158-
// update gateway status including the internal/external IPs and the nodes where the pods are running
159-
gw.Status.Workload.Nodes = make([]string, 0, len(pods))
160-
for _, pod := range pods {
161-
gw.Status.Workload.Nodes = append(gw.Status.Workload.Nodes, pod.Spec.NodeName)
162-
ips := util.PodIPs(*pod)
163-
ipv4, ipv6 := util.SplitIpsByProtocol(ips)
164-
if len(ipv4) != 0 {
165-
nodeNexthopIPv4[pod.Spec.NodeName] = ipv4[0]
166-
}
167-
if len(ipv6) != 0 {
168-
nodeNexthopIPv6[pod.Spec.NodeName] = ipv6[0]
169-
}
170-
gw.Status.InternalIPs = append(gw.Status.InternalIPs, strings.Join(ips, ","))
171-
extIPs, err := util.PodAttachmentIPs(pod, attachmentNetworkName)
172-
if err != nil {
173-
klog.Error(err)
174-
gw.Status.ExternalIPs = append(gw.Status.ExternalIPs, "<unknown>")
175-
continue
176-
}
177-
gw.Status.ExternalIPs = append(gw.Status.ExternalIPs, strings.Join(extIPs, ","))
171+
ips := util.PodIPs(*pod)
172+
ipv4, ipv6 := util.SplitIpsByProtocol(ips)
173+
if len(ipv4) != 0 {
174+
nodeNexthopIPv4[pod.Spec.NodeName] = ipv4[0]
175+
}
176+
if len(ipv6) != 0 {
177+
nodeNexthopIPv6[pod.Spec.NodeName] = ipv6[0]
178178
}
179+
gw.Status.InternalIPs = append(gw.Status.InternalIPs, strings.Join(ips, ","))
180+
gw.Status.ExternalIPs = append(gw.Status.ExternalIPs, strings.Join(extIPs, ","))
181+
gw.Status.Workload.Nodes = append(gw.Status.Workload.Nodes, pod.Spec.NodeName)
179182
}
180183
if gw, err = c.updateVpcEgressGatewayStatus(gw); err != nil {
181184
klog.Error(err)
182185
return err
183186
}
184-
if len(gw.Status.Workload.Nodes) == 0 {
185-
// the workload is not ready yet
186-
return nil
187-
}
188187

189188
// reconcile OVN routes
190189
if err = c.reconcileVpcEgressGatewayOVNRoutes(gw, 4, vpc.Status.Router, vpc.Status.BFDPort.Name, bfdIPv4, nodeNexthopIPv4, ipv4Src); err != nil {
@@ -196,11 +195,13 @@ func (c *Controller) handleAddOrUpdateVpcEgressGateway(key string) error {
196195
return err
197196
}
198197

199-
gw.Status.Ready = true
200-
gw.Status.Phase = kubeovnv1.PhaseCompleted
201-
gw.Status.Conditions.SetReady("ReconcileSuccess", gw.Generation)
202-
if _, err = c.updateVpcEgressGatewayStatus(gw); err != nil {
203-
return err
198+
if ready {
199+
gw.Status.Ready = true
200+
gw.Status.Phase = kubeovnv1.PhaseCompleted
201+
gw.Status.Conditions.SetReady("ReconcileSuccess", gw.Generation)
202+
if _, err = c.updateVpcEgressGatewayStatus(gw); err != nil {
203+
return err
204+
}
204205
}
205206

206207
return nil
@@ -606,17 +607,14 @@ func (c *Controller) reconcileVpcEgressGatewayOVNRoutes(gw *kubeovnv1.VpcEgressG
606607

607608
// reconcile OVN BFD entries
608609
bfdIDs := set.New[string]()
610+
staleBFDIDs := set.New[string]()
609611
bfdDstIPs := set.New(slices.Collect(maps.Values(nextHops))...)
610612
bfdMap := make(map[string]string, bfdDstIPs.Len())
611613
for _, bfd := range bfdList {
612614
if bfdIP == "" || bfd.LogicalPort != lrpName || !bfdDstIPs.Has(bfd.DstIP) {
613-
if err = c.OVNNbClient.DeleteBFD(bfd.UUID); err != nil {
614-
err = fmt.Errorf("failed to delete bfd %s: %w", bfd.UUID, err)
615-
klog.Error(err)
616-
return err
617-
}
615+
staleBFDIDs.Insert(bfd.UUID)
618616
}
619-
if bfdIP == "" || bfd.LogicalPort == lrpName && bfdDstIPs.Has(bfd.DstIP) {
617+
if bfdIP == "" || (bfd.LogicalPort == lrpName && bfdDstIPs.Has(bfd.DstIP)) {
620618
// TODO: update min_rx, min_tx and multiplier
621619
if bfdIP != "" {
622620
bfdIDs.Insert(bfd.UUID)
@@ -746,6 +744,47 @@ func (c *Controller) reconcileVpcEgressGatewayOVNRoutes(gw *kubeovnv1.VpcEgressG
746744
}
747745
}
748746

747+
if gw.Spec.BFD.Enabled {
748+
// drop traffic if no nexthop is available
749+
if policies, err = c.OVNNbClient.ListLogicalRouterPolicies(lrName, util.EgressGatewayDropPolicyPriority, externalIDs, false); err != nil {
750+
klog.Error(err)
751+
return err
752+
}
753+
matches = set.New(
754+
fmt.Sprintf("ip%d.src == $%s_ip%d", af, pgName, af),
755+
fmt.Sprintf("ip%d.src == $%s", af, asName),
756+
)
757+
for _, policy := range policies {
758+
if matches.Has(policy.Match) {
759+
matches.Delete(policy.Match)
760+
continue
761+
}
762+
if err = c.OVNNbClient.DeleteLogicalRouterPolicyByUUID(lrName, policy.UUID); err != nil {
763+
err = fmt.Errorf("failed to delete ovn lr policy %q: %w", policy.Match, err)
764+
klog.Error(err)
765+
return err
766+
}
767+
}
768+
for _, match := range matches.UnsortedList() {
769+
if err = c.OVNNbClient.AddLogicalRouterPolicy(lrName, util.EgressGatewayDropPolicyPriority, match,
770+
ovnnb.LogicalRouterPolicyActionDrop, nil, nil, externalIDs); err != nil {
771+
klog.Error(err)
772+
return err
773+
}
774+
}
775+
} else if err = c.OVNNbClient.DeleteLogicalRouterPolicies(lrName, util.EgressGatewayDropPolicyPriority, externalIDs); err != nil {
776+
klog.Error(err)
777+
return err
778+
}
779+
780+
for _, bfdID := range staleBFDIDs.UnsortedList() {
781+
if err = c.OVNNbClient.DeleteBFD(bfdID); err != nil {
782+
err = fmt.Errorf("failed to delete bfd %s: %w", bfdID, err)
783+
klog.Error(err)
784+
return err
785+
}
786+
}
787+
749788
return nil
750789
}
751790

pkg/util/const.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,12 @@ const (
214214
OvnFip = "ovn"
215215
IptablesFip = "iptables"
216216

217-
U2OSubnetPolicyPriority = 29400
218217
GatewayRouterPolicyPriority = 29000
218+
EgressGatewayDropPolicyPriority = 29090
219219
EgressGatewayPolicyPriority = 29100
220220
EgressGatewayLocalPolicyPriority = 29150
221221
NorthGatewayRoutePolicyPriority = 29250
222+
U2OSubnetPolicyPriority = 29400
222223
OvnICPolicyPriority = 29500
223224
NodeRouterPolicyPriority = 30000
224225
NodeLocalDNSPolicyPriority = 30100

0 commit comments

Comments
 (0)