Afford applying nft commands via libnftables without needing to go
through our table abstraction. Make the table abstraction responsible
for lazily allocating an nft context.
Signed-off-by: Cory Snider <csnider@mirantis.com>
| ... | ... |
@@ -20,28 +20,19 @@ import ( |
| 20 | 20 |
// #include <nftables/libnftables.h> |
| 21 | 21 |
import "C" |
| 22 | 22 |
|
| 23 |
-type nftHandle = *C.struct_nft_ctx |
|
| 23 |
+type nftCtx C.struct_nft_ctx |
|
| 24 | 24 |
|
| 25 |
-// nftApply calls libnftables to execute the nftables commands in nftCmd. |
|
| 26 |
-// Acquire t.applyLock before calling this function. |
|
| 27 |
-func (t *table) nftApply(ctx context.Context, nftCmd []byte) error {
|
|
| 25 |
+// Apply calls libnftables to execute the nftables commands in nftCmd. |
|
| 26 |
+func (h *nftCtx) Apply(ctx context.Context, nftCmd []byte) error {
|
|
| 28 | 27 |
ctx, span := otel.Tracer("").Start(ctx, spanPrefix+".nftApply.cgo")
|
| 29 | 28 |
defer span.End() |
| 30 | 29 |
|
| 31 |
- if t.nftHandle == nil {
|
|
| 32 |
- handle, err := newNftHandle() |
|
| 33 |
- if err != nil {
|
|
| 34 |
- return err |
|
| 35 |
- } |
|
| 36 |
- t.nftHandle = handle |
|
| 37 |
- } |
|
| 38 |
- |
|
| 39 | 30 |
cCmd := C.CString(string(nftCmd)) |
| 40 | 31 |
defer C.free(unsafe.Pointer(cCmd)) |
| 41 | 32 |
|
| 42 |
- ret := C.nft_run_cmd_from_buffer(t.nftHandle, cCmd) |
|
| 43 |
- stdout := C.GoString(C.nft_ctx_get_output_buffer(t.nftHandle)) |
|
| 44 |
- stderr := C.GoString(C.nft_ctx_get_error_buffer(t.nftHandle)) |
|
| 33 |
+ ret := C.nft_run_cmd_from_buffer((*C.struct_nft_ctx)(h), cCmd) |
|
| 34 |
+ stdout := C.GoString(C.nft_ctx_get_output_buffer((*C.struct_nft_ctx)(h))) |
|
| 35 |
+ stderr := C.GoString(C.nft_ctx_get_error_buffer((*C.struct_nft_ctx)(h))) |
|
| 45 | 36 |
if ret != 0 {
|
| 46 | 37 |
return fmt.Errorf("libnftables: failed to apply commands (code %d), stderr: %s", int(ret), stderr)
|
| 47 | 38 |
} |
| ... | ... |
@@ -49,7 +40,7 @@ func (t *table) nftApply(ctx context.Context, nftCmd []byte) error {
|
| 49 | 49 |
return nil |
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 |
-func newNftHandle() (_ *C.struct_nft_ctx, retErr error) {
|
|
| 52 |
+func newNftCtx() (_ *nftCtx, retErr error) {
|
|
| 53 | 53 |
handle := C.nft_ctx_new(C.NFT_CTX_DEFAULT) |
| 54 | 54 |
if handle == nil {
|
| 55 | 55 |
return nil, errors.New("libnftables: failed to create new nft handle")
|
| ... | ... |
@@ -65,14 +56,9 @@ func newNftHandle() (_ *C.struct_nft_ctx, retErr error) {
|
| 65 | 65 |
if ret := C.nft_ctx_buffer_error(handle); ret != 0 {
|
| 66 | 66 |
return nil, fmt.Errorf("libnftables: failed to set error buffer (code %d)", int(ret))
|
| 67 | 67 |
} |
| 68 |
- return handle, nil |
|
| 68 |
+ return (*nftCtx)(handle), nil |
|
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
-func (t *table) closeNftHandle() {
|
|
| 72 |
- t.applyLock.Lock() |
|
| 73 |
- defer t.applyLock.Unlock() |
|
| 74 |
- if t.nftHandle != nil {
|
|
| 75 |
- C.nft_ctx_free(t.nftHandle) |
|
| 76 |
- t.nftHandle = nil |
|
| 77 |
- } |
|
| 71 |
+func (h *nftCtx) Close() {
|
|
| 72 |
+ C.nft_ctx_free((*C.struct_nft_ctx)(h)) |
|
| 78 | 73 |
} |
| ... | ... |
@@ -15,13 +15,17 @@ import ( |
| 15 | 15 |
"go.opentelemetry.io/otel" |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 |
-type nftHandle = struct{}
|
|
| 18 |
+type nftCtx struct{}
|
|
| 19 | 19 |
|
| 20 | 20 |
var lookPathNSEnter = sync.OnceValues(func() (string, error) {
|
| 21 | 21 |
return exec.LookPath("nsenter")
|
| 22 | 22 |
}) |
| 23 | 23 |
|
| 24 |
-func (t *table) nftApply(ctx context.Context, nftCmd []byte) error {
|
|
| 24 |
+func newNftCtx() (*nftCtx, error) {
|
|
| 25 |
+ return *nftCtx{}, nil
|
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func (*nftCtx) Apply(ctx context.Context, nftCmd []byte) error {
|
|
| 25 | 29 |
ctx, span := otel.Tracer("").Start(ctx, spanPrefix+".nftApply.exec")
|
| 26 | 30 |
defer span.End() |
| 27 | 31 |
|
| ... | ... |
@@ -82,5 +86,5 @@ func (t *table) nftApply(ctx context.Context, nftCmd []byte) error {
|
| 82 | 82 |
return nil |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
-func (t *table) closeNftHandle() {
|
|
| 85 |
+func (*nftCtx) Close() {
|
|
| 86 | 86 |
} |
| ... | ... |
@@ -258,7 +258,20 @@ type table struct {
|
| 258 | 258 |
MustFlush bool |
| 259 | 259 |
|
| 260 | 260 |
applyLock sync.Mutex |
| 261 |
- nftHandle nftHandle // applyLock must be held to access |
|
| 261 |
+ nftHandle *nftCtx // applyLock must be held to access |
|
| 262 |
+} |
|
| 263 |
+ |
|
| 264 |
+// nftApply executes the nftables commands in nftCmd. |
|
| 265 |
+// Acquire t.applyLock before calling this function. |
|
| 266 |
+func (t *table) nftApply(ctx context.Context, nftCmd []byte) error {
|
|
| 267 |
+ if t.nftHandle == nil {
|
|
| 268 |
+ h, err := newNftCtx() |
|
| 269 |
+ if err != nil {
|
|
| 270 |
+ return err |
|
| 271 |
+ } |
|
| 272 |
+ t.nftHandle = h |
|
| 273 |
+ } |
|
| 274 |
+ return t.nftHandle.Apply(ctx, nftCmd) |
|
| 262 | 275 |
} |
| 263 | 276 |
|
| 264 | 277 |
// Table is a handle for an nftables table. |
| ... | ... |
@@ -305,7 +318,12 @@ func NewTable(family Family, name string) (Table, error) {
|
| 305 | 305 |
// the underlying nftables table. |
| 306 | 306 |
func (t Table) Close() error {
|
| 307 | 307 |
if t.IsValid() {
|
| 308 |
- t.t.closeNftHandle() |
|
| 308 |
+ t.t.applyLock.Lock() |
|
| 309 |
+ defer t.t.applyLock.Unlock() |
|
| 310 |
+ if t.t.nftHandle != nil {
|
|
| 311 |
+ t.t.nftHandle.Close() |
|
| 312 |
+ t.t.nftHandle = nil |
|
| 313 |
+ } |
|
| 309 | 314 |
t.t = nil |
| 310 | 315 |
} |
| 311 | 316 |
return nil |