Skip to content

Commit

Permalink
[BPF] host can access self via a service without CTLB
Browse files Browse the repository at this point in the history
added test for this case

No host source conflict resolution on lo since we cannot tell traffic
straight to self from traffic to self via a service. Host connecting to
self and connecting to the same self port via a service should be rare,
but if that is necessaty, than CTLB is the only option.
  • Loading branch information
tomastigera committed Mar 2, 2024
1 parent 222bb27 commit 16582c4
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
16 changes: 16 additions & 0 deletions felix/bpf-gpl/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ int calico_tc_main(struct __sk_buff *skb)
*/
skb->mark = SKB_MARK;
#endif

if (CALI_F_LO && CALI_F_TO_HOST) {
/* Do nothing, it is a packet that just looped around. */
return TC_ACT_UNSPEC;
}

/* Optimisation: if another BPF program has already pre-approved the packet,
* skip all processing. */
if (CALI_F_FROM_HOST && skb->mark == CALI_SKB_MARK_BYPASS) {
Expand Down Expand Up @@ -263,6 +269,16 @@ static CALI_BPF_INLINE void calico_tc_process_ct_lookup(struct cali_tc_ctx *ctx)
skb_mark_equals(ctx->skb, CALI_SKB_MARK_BYPASS_MASK, CALI_SKB_MARK_SKIP_FIB)));

if (HAS_HOST_CONFLICT_PROG &&
/* Do not do conflict resolution for host-self loop. Unlike with
* traffic to another backend, we are not able to tell traffic to
* self via service from straight to self.
*/
!CALI_F_LO &&
/* Do conflict resolution on other device if it clashes with
* traffic looped via the NAT_IF but it hasn't been seen yet and
* is not looped via the NAT_IF, that is, it is from host, but not
* to a service.
*/
(ctx->state->ct_result.flags & CALI_CT_FLAG_VIA_NAT_IF) &&
!(ctx->skb->mark & (CALI_SKB_MARK_FROM_NAT_IFACE_OUT | CALI_SKB_MARK_SEEN))) {
CALI_DEBUG("Host source SNAT conflict\n");
Expand Down
29 changes: 29 additions & 0 deletions felix/fv/bpf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4285,6 +4285,35 @@ func describeBPFTests(opts ...bpfTestOpt) bool {
})
})

It("should have connectivity from host-networked pods via service to host-networked backend", func() {
By("Setting up the service")
hostW[0].ConfigureInInfra(infra)
testSvc := k8sService("host-svc", clusterIP, hostW[0], 80, 8055, 0, testOpts.protocol)
testSvcNamespace := testSvc.ObjectMeta.Namespace
k8sClient := infra.(*infrastructure.K8sDatastoreInfra).K8sClient
_, err := k8sClient.CoreV1().Services(testSvcNamespace).Create(context.Background(), testSvc, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
Eventually(k8sGetEpsForServiceFunc(k8sClient, testSvc), "10s").Should(HaveLen(1),
"Service endpoints didn't get created? Is controller-manager happy?")

By("Testing connectivity")
port := uint16(testSvc.Spec.Ports[0].Port)

hostW0SrcIP := ExpectWithSrcIPs(felixIP(0))
hostW1SrcIP := ExpectWithSrcIPs(felixIP(1))
if !testOpts.connTimeEnabled {
switch testOpts.tunnel {
case "ipip":
hostW0SrcIP = ExpectWithSrcIPs(tc.Felixes[0].ExpectedIPIPTunnelAddr)
hostW1SrcIP = ExpectWithSrcIPs(tc.Felixes[1].ExpectedIPIPTunnelAddr)
}
}

cc.Expect(Some, hostW[0], TargetIP(clusterIP), ExpectWithPorts(port), hostW0SrcIP)
cc.Expect(Some, hostW[1], TargetIP(clusterIP), ExpectWithPorts(port), hostW1SrcIP)
cc.CheckConnectivity()
})

})

Describe("with BPF disabled to begin with", func() {
Expand Down

0 comments on commit 16582c4

Please sign in to comment.