Repository: moby/moby
File: daemon/libnetwork/drivers/bridge/internal/nftabler/nftabler.go (Go)

Code before:

	if nft.config.IPv4 {
		var err error
		nft.table4, err = nft.init(ctx, nftables.IPv4)
		if err != nil {
			return nil, err
		}
	}

	if nft.config.IPv6 {
		var err error
		nft.table6, err = nft.init(ctx, nftables.IPv6)
		if err != nil {
			return nil, err
		}
	}

	return nft, nil
}

// Close releases resources held by the Nftabler, the underlying nftables tables
// are not modified or deleted.
func (nft *Nftabler) Close() error {
	_ = nft.table4.Close()
	_ = nft.table6.Close()
	return nil
}

func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables.Table, error) {
	// Instantiate the table.
	table, err := nftables.NewTable(family, dockerTable)
	if err != nil {
		return table, err
	}
	tm := nftables.Modifier{}

	// Set up the filter forward chain.
	//
	// This base chain only contains two rules that use verdict maps:
	// - if a packet is entering a bridge network, jump to that network's filter-forward ingress chain.
	// - if a packet is leaving a bridge network, jump to that network's filter-forward egress chain.
	//
	// So, packets that aren't related to docker don't need to traverse any per-network filter forward
	// rules - and packets that are entering or leaving docker networks only need to traverse rules
	// related to those networks.
	tm.Create(nftables.BaseChain{
		Name:      forwardChain,
		ChainType: nftables.BaseChainTypeFilter,
		Hook:      nftables.BaseChainHookForward,
		Priority:  nftables.BaseChainPriorityFilter,
	})

Review comment (suggestion):
```suggestion
	return errors.Join(nft.table4.Close(), nft.table6.Close())
```

Code after:
	nft := &Nftabler{config: config}

	if nft.config.IPv4 {
		var err error
		nft.table4, err = nft.init(ctx, nftables.IPv4)
		if err != nil {
			return nil, err
		}
	}

	if nft.config.IPv6 {
		var err error
		nft.table6, err = nft.init(ctx, nftables.IPv6)
		if err != nil {
			return nil, err
		}
	}

	return nft, nil
}

// Close releases resources held by the Nftabler, the underlying nftables tables
// are not modified or deleted.
func (nft *Nftabler) Close() error {
	return errors.Join(nft.table4.Close(), nft.table6.Close())
}

func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables.Table, error) {
	// Instantiate the table.
	table, err := nftables.NewTable(family, dockerTable)
	if err != nil {
		return table, err
	}
	tm := nftables.Modifier{}

	// Set up the filter forward chain.
	//
	// This base chain only contains two rules that use verdict maps:
	// - if a packet is entering a bridge network, jump to that network's filter-forward ingress chain.
	// - if a packet is leaving a bridge network, jump to that network's filter-forward egress chain.
	//
	// So, packets that aren't related to docker don't need to traverse any per-network filter forward
	// rules - and packets that are entering or leaving docker networks only need to traverse rules
	// related to those networks.
	tm.Create(nftables.BaseChain{
		Name:      forwardChain,
		ChainType: nftables.BaseChainTypeFilter,
		Hook:      nftables.BaseChainHookForward,
		Priority:  nftables.BaseChainPriorityFilter,
	})
	// Instantiate the verdict maps and add the jumps.