Skip to content

Commit d099e91

Browse files
committed
[tunnel] Allocate v4 addrs via IPAM
1 parent 770cc11 commit d099e91

File tree

7 files changed

+71
-38
lines changed

7 files changed

+71
-38
lines changed

api/core/v1alpha/tunnel_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ type AgentStatus struct {
5656
// Overlay address of the agent. Currently we're using a /96 prefix which
5757
// can be used for 4in6 tunneling.
5858
AgentAddress string `json:"agentAddress,omitempty"`
59+
60+
// Extra addresses of the agent (for additional v4/v6 overlays, if configured).
61+
// +optional
62+
AgentAddresses []string `json:"agentAddresses,omitempty"`
5963
}
6064

6165
type TunnelNodeCredentials struct {

api/core/v1alpha/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/generated/zz_generated.openapi.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apiserver/controllers/tunnelnode.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type TunnelNodeReconciler struct {
3333
jwtPrivateKeyPEM []byte
3434
jwtPublicKeyPEM []byte
3535
tokenRefreshThreshold time.Duration
36-
agentIPAM tunnet.IPAM
36+
ipamv6, ipamv4 tunnet.IPAM
3737

3838
validator *token.InMemoryValidator
3939
issuer *token.Issuer
@@ -46,7 +46,7 @@ func NewTunnelNodeReconciler(
4646
jwtPrivateKey []byte,
4747
jwtPublicKey []byte,
4848
tokenRefreshThreshold time.Duration,
49-
agentIPAM tunnet.IPAM,
49+
ipamv6, ipamv4 tunnet.IPAM,
5050
) *TunnelNodeReconciler {
5151
return &TunnelNodeReconciler{
5252
Client: c,
@@ -55,7 +55,8 @@ func NewTunnelNodeReconciler(
5555
jwtPrivateKeyPEM: jwtPrivateKey,
5656
jwtPublicKeyPEM: jwtPublicKey,
5757
tokenRefreshThreshold: tokenRefreshThreshold,
58-
agentIPAM: agentIPAM,
58+
ipamv6: ipamv6,
59+
ipamv4: ipamv4,
5960
}
6061
}
6162

@@ -133,7 +134,7 @@ func (r *TunnelNodeReconciler) Reconcile(ctx context.Context, req reconcile.Requ
133134
log.Error(err, "Failed to parse IP address", "addr", agent.AgentAddress)
134135
continue
135136
}
136-
if err := r.agentIPAM.Release(netip.PrefixFrom(addr, 96)); err != nil {
137+
if err := r.ipamv6.Release(netip.PrefixFrom(addr, 96)); err != nil {
137138
log.Error(err, "Failed to release IP address", "addr", addr)
138139
}
139140
}
@@ -192,18 +193,27 @@ func (r *TunnelNodeReconciler) Reconcile(ctx context.Context, req reconcile.Requ
192193
continue
193194
}
194195

195-
addr, err := r.agentIPAM.Allocate()
196+
addrv6, err := r.ipamv6.Allocate()
196197
if err != nil {
197198
return ctrl.Result{}, fmt.Errorf("failed to allocate agent address: %w", err)
198199
}
199200

200-
log.Info("Allocated agent address", "agent", agent.Name, "addr", addr)
201+
log.Info("Allocated agent v6 address", "agent", agent.Name, "addr", addrv6)
201202

202-
tn.Status.Agents[i].AgentAddress = addr.Addr().String()
203+
tn.Status.Agents[i].AgentAddress = addrv6.Addr().String()
204+
205+
addrv4, err := r.ipamv4.Allocate()
206+
if err != nil {
207+
return ctrl.Result{}, fmt.Errorf("failed to allocate agent address: %w", err)
208+
}
209+
210+
log.Info("Allocated agent v4 address", "agent", agent.Name, "addr", addrv4)
211+
212+
tn.Status.Agents[i].AgentAddresses = append(tn.Status.Agents[i].AgentAddresses, addrv4.Addr().String())
203213

204214
if err := r.Status().Update(ctx, tn); err != nil {
205-
if err := r.agentIPAM.Release(addr); err != nil {
206-
log.Error(err, "Failed to release agent address", "agent", agent.Name, "addr", addr)
215+
if err := r.ipamv6.Release(addrv6); err != nil {
216+
log.Error(err, "Failed to release agent address", "agent", agent.Name, "addr", addrv6)
207217
}
208218
return ctrl.Result{}, fmt.Errorf("failed to update status: %w", err)
209219
}

pkg/apiserver/controllers/tunnelnode_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestTunnelNodeReconciler(t *testing.T) {
4444

4545
systemULA := tunnet.NewULA(context.Background(), net.SystemNetworkID)
4646
// Agent prefixes are /96 subnets that can embed IPv4 suffixes.
47-
agentIPAM, err := systemULA.IPAM(context.Background(), 96)
47+
ipamv6, err := systemULA.IPAM(context.Background(), 96)
4848
require.NoError(t, err)
4949

5050
r := NewTunnelNodeReconciler(
@@ -54,15 +54,15 @@ func TestTunnelNodeReconciler(t *testing.T) {
5454
privKey,
5555
pubKey,
5656
time.Minute,
57-
agentIPAM,
57+
ipamv6,
58+
net.NewIPAMv4(context.Background()),
5859
)
5960

6061
r.validator, err = token.NewInMemoryValidator(r.jwtPublicKeyPEM)
6162
require.NoError(t, err)
6263
r.issuer, err = token.NewIssuer(r.jwtPrivateKeyPEM)
6364
require.NoError(t, err)
6465

65-
// Call the reconcile method.
6666
_, err = r.Reconcile(context.TODO(), reconcile.Request{
6767
NamespacedName: types.NamespacedName{
6868
Name: "test-tunnelnode",

pkg/apiserver/manager.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import (
4747
"github.com/apoxy-dev/apoxy/pkg/cryptoutils"
4848
gw "github.com/apoxy-dev/apoxy/pkg/gateway"
4949
"github.com/apoxy-dev/apoxy/pkg/log"
50-
"github.com/apoxy-dev/apoxy/pkg/tunnel/net"
50+
apoxynet "github.com/apoxy-dev/apoxy/pkg/tunnel/net"
5151
tunnet "github.com/apoxy-dev/apoxy/pkg/tunnel/net"
5252

5353
ctrlv1alpha1 "github.com/apoxy-dev/apoxy/api/controllers/v1alpha1"
@@ -352,15 +352,15 @@ func encodeSQLiteConnArgs(args map[string]string) string {
352352

353353
// defaultOptions returns default options.
354354
func defaultOptions(ctx context.Context) (*options, error) {
355-
systemULA := tunnet.NewULA(ctx, net.SystemNetworkID)
355+
systemULA := tunnet.NewULA(ctx, apoxynet.SystemNetworkID)
356356
// Agent prefixes are /96 subnets that can embed IPv4 suffixes.
357357
agentIPAM, err := systemULA.IPAM(ctx, 96)
358358
if err != nil {
359359
return nil, fmt.Errorf("failed to create agent IPAM: %w", err)
360360
}
361361

362362
// Proxy prefixes are /128 leafs under reserved proxy endpoint.
363-
epULA, err := systemULA.WithEndpoint(ctx, net.ProxyEndpointID)
363+
epULA, err := systemULA.WithEndpoint(ctx, apoxynet.ProxyEndpointID)
364364
if err != nil {
365365
return nil, fmt.Errorf("failed to create proxy endpoint: %w", err)
366366
}
@@ -486,6 +486,7 @@ func (m *Manager) Start(
486486
dOpts.jwtPublicKey,
487487
dOpts.jwtRefreshThreshold,
488488
dOpts.agentIPAM,
489+
apoxynet.NewIPAMv4(context.Background()),
489490
)
490491
if err := tunnelNodeReconciler.SetupWithManager(ctx, m.manager); err != nil {
491492
return fmt.Errorf("failed to set up TunnelNode controller: %v", err)

pkg/tunnel/server.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ func (t *TunnelServer) reconcile(ctx context.Context, request reconcile.Request)
586586
}
587587

588588
// Check if we already allocated and assigned addresses.
589-
if conn.addrv6.IsValid() /*&& conn.addrv4.IsValid()*/ {
589+
if conn.addrv6.IsValid() && conn.addrv4.IsValid() {
590590
log.V(1).Info("Agent address is already assigned")
591591
continue
592592
}
@@ -606,18 +606,18 @@ func (t *TunnelServer) reconcile(ctx context.Context, request reconcile.Request)
606606
}
607607
t.conns.Set(agent.Name, conn)
608608

609-
// TODO(dilyevsky): v4 prefix should also be delivered via agent status
610-
// struct (needs api change to support multiple addresses).
611-
/*
612-
if !conn.addrv4.IsValid() {
613-
var err error
614-
conn.addrv4, err = t.options.ipamv4.Allocate()
615-
if err != nil {
616-
log.Error(err, "Failed to allocate IPv4 address")
617-
continue
609+
if !conn.addrv4.IsValid() {
610+
for _, agentAddr := range agent.AgentAddresses {
611+
if addr, err := netip.ParseAddr(agentAddr); err == nil && addr.Is4() {
612+
conn.addrv4 = netip.PrefixFrom(addr, 32)
613+
break
618614
}
619615
}
620-
*/
616+
if !conn.addrv4.IsValid() {
617+
log.Info("No IPv4 address allocated")
618+
continue
619+
}
620+
}
621621
t.conns.Set(agent.Name, conn)
622622

623623
log.Info("Assigned addresses to connection",
@@ -642,18 +642,16 @@ func (t *TunnelServer) reconcile(ctx context.Context, request reconcile.Request)
642642
metrics.TunnelConnectionFailures.WithLabelValues("route_addition_failed").Inc()
643643
return reconcile.Result{}, nil
644644
}
645-
/*
646-
if err := t.router.AddAddr(conn.addrv4, conn); err != nil {
647-
log.Error(err, "Failed to add TUN peer")
648-
metrics.TunnelConnectionFailures.WithLabelValues("tun_peer_add_failed").Inc()
649-
return reconcile.Result{}, nil
650-
}
651-
if err := t.router.AddRoute(conn.addrv4); err != nil {
652-
log.Error(err, "Failed to add route")
653-
metrics.TunnelConnectionFailures.WithLabelValues("route_addition_failed").Inc()
654-
return reconcile.Result{}, nil
655-
}
656-
*/
645+
if err := t.router.AddAddr(conn.addrv4, conn); err != nil {
646+
log.Error(err, "Failed to add TUN peer")
647+
metrics.TunnelConnectionFailures.WithLabelValues("tun_peer_add_failed").Inc()
648+
return reconcile.Result{}, nil
649+
}
650+
if err := t.router.AddRoute(conn.addrv4); err != nil {
651+
log.Error(err, "Failed to add route")
652+
metrics.TunnelConnectionFailures.WithLabelValues("route_addition_failed").Inc()
653+
return reconcile.Result{}, nil
654+
}
657655

658656
metrics.TunnelConnectionsActive.Inc()
659657
defer metrics.TunnelConnectionsActive.Dec()

0 commit comments

Comments
 (0)