An nftables vmap is just a map whose element values are of type
`verdict`. Generalize VMap, VMapElement and Set to support any element
type.
Add a fluent API to build arbitrary tuple and mapping types from the
composition of other types or the 'typeof' an nftables expression.
Block the invalid composition of named types and `typeof` expressions at
compile time.
There are only a handful of contexts where the data type needs to be
specified: set and map definitions. Modelling set and map types as a
singular "nft type" does not align well with the semantics of nftables.
Map types are always composite types with a key and a value part. Set
types do not have a value part; it is an error to create a map with a
set type or vice versa. Encode this distinction into the Go type system
so it is a compile-time error to try to use a set type in a map context
or a map type in a set context.
Drop the 'NftType' prefix from the primitive set-type constants. The
prefix stutters with the package name and, as discussed above, it is not
accurate to call them "nft types." Verdicts cannot be used as set
elements or map keys. Provide dedicated methods to construct verdict-map
types from set types instead of modelling verdicts as types themselves.
Signed-off-by: Cory Snider <csnider@mirantis.com>
| ... | ... |
@@ -67,31 +67,31 @@ func (n *network) configure(ctx context.Context, table nftables.Table, conf fire |
| 67 | 67 |
tm.Create(nftables.Chain{Name: fwdInChain})
|
| 68 | 68 |
tm.Create(nftables.Chain{Name: fwdOutChain})
|
| 69 | 69 |
|
| 70 |
- tm.Create(nftables.VMapElement{
|
|
| 71 |
- VmapName: filtFwdInVMap, |
|
| 72 |
- Key: n.config.IfName, |
|
| 73 |
- Verdict: "jump " + fwdInChain, |
|
| 70 |
+ tm.Create(nftables.MapElement{
|
|
| 71 |
+ MapName: filtFwdInVMap, |
|
| 72 |
+ Key: n.config.IfName, |
|
| 73 |
+ Value: "jump " + fwdInChain, |
|
| 74 | 74 |
}) |
| 75 |
- tm.Create(nftables.VMapElement{
|
|
| 76 |
- VmapName: filtFwdOutVMap, |
|
| 77 |
- Key: n.config.IfName, |
|
| 78 |
- Verdict: "jump " + fwdOutChain, |
|
| 75 |
+ tm.Create(nftables.MapElement{
|
|
| 76 |
+ MapName: filtFwdOutVMap, |
|
| 77 |
+ Key: n.config.IfName, |
|
| 78 |
+ Value: "jump " + fwdOutChain, |
|
| 79 | 79 |
}) |
| 80 | 80 |
|
| 81 | 81 |
// NAT chain |
| 82 | 82 |
|
| 83 | 83 |
tm.Create(nftables.Chain{Name: natPostRtInChain})
|
| 84 |
- tm.Create(nftables.VMapElement{
|
|
| 85 |
- VmapName: natPostroutingInVMap, |
|
| 86 |
- Key: n.config.IfName, |
|
| 87 |
- Verdict: "jump " + natPostRtInChain, |
|
| 84 |
+ tm.Create(nftables.MapElement{
|
|
| 85 |
+ MapName: natPostroutingInVMap, |
|
| 86 |
+ Key: n.config.IfName, |
|
| 87 |
+ Value: "jump " + natPostRtInChain, |
|
| 88 | 88 |
}) |
| 89 | 89 |
|
| 90 | 90 |
tm.Create(nftables.Chain{Name: chainNatPostRtOut(n.config.IfName)})
|
| 91 |
- tm.Create(nftables.VMapElement{
|
|
| 92 |
- VmapName: natPostroutingOutVMap, |
|
| 93 |
- Key: n.config.IfName, |
|
| 94 |
- Verdict: "jump " + chainNatPostRtOut(n.config.IfName), |
|
| 91 |
+ tm.Create(nftables.MapElement{
|
|
| 92 |
+ MapName: natPostroutingOutVMap, |
|
| 93 |
+ Key: n.config.IfName, |
|
| 94 |
+ Value: "jump " + chainNatPostRtOut(n.config.IfName), |
|
| 95 | 95 |
}) |
| 96 | 96 |
|
| 97 | 97 |
// Conntrack |
| ... | ... |
@@ -105,9 +105,9 @@ func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables |
| 105 | 105 |
Priority: nftables.BaseChainPriorityFilter, |
| 106 | 106 |
}) |
| 107 | 107 |
// Instantiate the verdict maps and add the jumps. |
| 108 |
- tm.Create(nftables.VMap{
|
|
| 108 |
+ tm.Create(nftables.Map{
|
|
| 109 | 109 |
Name: filtFwdInVMap, |
| 110 |
- ElementType: nftables.NftTypeIfname, |
|
| 110 |
+ ElementType: nftables.Ifname.VMap(), |
|
| 111 | 111 |
}) |
| 112 | 112 |
tm.Create(nftables.Rule{
|
| 113 | 113 |
Chain: forwardChain, |
| ... | ... |
@@ -115,9 +115,9 @@ func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables |
| 115 | 115 |
Rule: []string{"oifname vmap @", filtFwdInVMap},
|
| 116 | 116 |
}) |
| 117 | 117 |
|
| 118 |
- tm.Create(nftables.VMap{
|
|
| 118 |
+ tm.Create(nftables.Map{
|
|
| 119 | 119 |
Name: filtFwdOutVMap, |
| 120 |
- ElementType: nftables.NftTypeIfname, |
|
| 120 |
+ ElementType: nftables.Ifname.VMap(), |
|
| 121 | 121 |
}) |
| 122 | 122 |
tm.Create(nftables.Rule{
|
| 123 | 123 |
Chain: forwardChain, |
| ... | ... |
@@ -135,9 +135,9 @@ func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables |
| 135 | 135 |
Priority: nftables.BaseChainPrioritySrcNAT, |
| 136 | 136 |
}) |
| 137 | 137 |
|
| 138 |
- tm.Create(nftables.VMap{
|
|
| 138 |
+ tm.Create(nftables.Map{
|
|
| 139 | 139 |
Name: natPostroutingOutVMap, |
| 140 |
- ElementType: nftables.NftTypeIfname, |
|
| 140 |
+ ElementType: nftables.Ifname.VMap(), |
|
| 141 | 141 |
}) |
| 142 | 142 |
tm.Create(nftables.Rule{
|
| 143 | 143 |
Chain: postroutingChain, |
| ... | ... |
@@ -145,9 +145,9 @@ func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables |
| 145 | 145 |
Rule: []string{"iifname vmap @", natPostroutingOutVMap},
|
| 146 | 146 |
}) |
| 147 | 147 |
|
| 148 |
- tm.Create(nftables.VMap{
|
|
| 148 |
+ tm.Create(nftables.Map{
|
|
| 149 | 149 |
Name: natPostroutingInVMap, |
| 150 |
- ElementType: nftables.NftTypeIfname, |
|
| 150 |
+ ElementType: nftables.Ifname.VMap(), |
|
| 151 | 151 |
}) |
| 152 | 152 |
tm.Create(nftables.Rule{
|
| 153 | 153 |
Chain: postroutingChain, |
| ... | ... |
@@ -14,7 +14,7 @@ |
| 14 | 14 |
// // Apply the updates with ... |
| 15 | 15 |
// err := tm.Apply(ctx) |
| 16 | 16 |
// |
| 17 |
-// The objects are any of: [BaseChain], [Chain], [Rule], [VMap], [VMapElement], |
|
| 17 |
+// The objects are any of: [BaseChain], [Chain], [Rule], [Map], [MapElement], |
|
| 18 | 18 |
// [Set], [SetElement] |
| 19 | 19 |
// |
| 20 | 20 |
// The modifier can be reused to apply the same set of commands again or, more |
| ... | ... |
@@ -128,19 +128,86 @@ const ( |
| 128 | 128 |
IPv6 Family = "ip6" |
| 129 | 129 |
) |
| 130 | 130 |
|
| 131 |
-// NftType enumerates nft types that can be used to define maps/sets etc. |
|
| 132 |
-type NftType string |
|
| 131 |
+type SetTyper interface {
|
|
| 132 |
+ setType() string |
|
| 133 |
+} |
|
| 134 |
+ |
|
| 135 |
+type MapTyper interface {
|
|
| 136 |
+ mapType() string |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+// SetType represents named nft types that can be used to define sets or |
|
| 140 |
+// construct map types. |
|
| 141 |
+type SetType string |
|
| 133 | 142 |
|
| 134 | 143 |
const ( |
| 135 |
- NftTypeIPv4Addr NftType = "ipv4_addr" |
|
| 136 |
- NftTypeIPv6Addr NftType = "ipv6_addr" |
|
| 137 |
- NftTypeEtherAddr NftType = "ether_addr" |
|
| 138 |
- NftTypeInetProto NftType = "inet_proto" |
|
| 139 |
- NftTypeInetService NftType = "inet_service" |
|
| 140 |
- NftTypeMark NftType = "mark" |
|
| 141 |
- NftTypeIfname NftType = "ifname" |
|
| 144 |
+ IPv4Addr SetType = "ipv4_addr" |
|
| 145 |
+ IPv6Addr SetType = "ipv6_addr" |
|
| 146 |
+ EtherAddr SetType = "ether_addr" |
|
| 147 |
+ InetProto SetType = "inet_proto" |
|
| 148 |
+ InetService SetType = "inet_service" |
|
| 149 |
+ Mark SetType = "mark" |
|
| 150 |
+ Ifname SetType = "ifname" |
|
| 142 | 151 |
) |
| 143 | 152 |
|
| 153 |
+func (t SetType) setType() string {
|
|
| 154 |
+ return "type " + string(t) |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+// Concat returns the tuple type formed by concatenating t and u. |
|
| 158 |
+func (t SetType) Concat(u SetType) SetType {
|
|
| 159 |
+ return SetType(string(t) + " . " + string(u)) |
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+// MapType represents the named type of a map element, which is a compound type |
|
| 163 |
+// with a key and a value. |
|
| 164 |
+type MapType string |
|
| 165 |
+ |
|
| 166 |
+func (t MapType) mapType() string {
|
|
| 167 |
+ return "type " + string(t) |
|
| 168 |
+} |
|
| 169 |
+ |
|
| 170 |
+// MapTo returns the map type where t is the key type and v is the value type. |
|
| 171 |
+func (t SetType) MapTo(v SetType) MapType {
|
|
| 172 |
+ return MapType(string(t) + " : " + string(v)) |
|
| 173 |
+} |
|
| 174 |
+ |
|
| 175 |
+// VMap returns the map type whose elements have t as the key type and contain |
|
| 176 |
+// a verdict as the value. |
|
| 177 |
+func (t SetType) VMap() MapType {
|
|
| 178 |
+ return MapType(string(t) + " : verdict") |
|
| 179 |
+} |
|
| 180 |
+ |
|
| 181 |
+// Typeof represents an nft "typeof" expression. |
|
| 182 |
+type Typeof string |
|
| 183 |
+ |
|
| 184 |
+func (t Typeof) setType() string {
|
|
| 185 |
+ return "typeof " + string(t) |
|
| 186 |
+} |
|
| 187 |
+ |
|
| 188 |
+func (t Typeof) Concat(u Typeof) Typeof {
|
|
| 189 |
+ return Typeof(string(t) + " . " + string(u)) |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+// MapTypeof represents the type of a map element defined by a "typeof" |
|
| 193 |
+// expression. |
|
| 194 |
+type MapTypeof string |
|
| 195 |
+ |
|
| 196 |
+func (t MapTypeof) mapType() string {
|
|
| 197 |
+ return "typeof " + string(t) |
|
| 198 |
+} |
|
| 199 |
+ |
|
| 200 |
+// MapTo returns the map type where t is the key type and v is the value type. |
|
| 201 |
+func (t Typeof) MapTo(v Typeof) MapTypeof {
|
|
| 202 |
+ return MapTypeof(string(t) + " : " + string(v)) |
|
| 203 |
+} |
|
| 204 |
+ |
|
| 205 |
+// VMap returns the map type whose elements have t as the key type and contain |
|
| 206 |
+// a verdict as the value. |
|
| 207 |
+func (t Typeof) VMap() MapTypeof {
|
|
| 208 |
+ return MapTypeof(string(t) + " : verdict") |
|
| 209 |
+} |
|
| 210 |
+ |
|
| 144 | 211 |
// Enable tries once to initialise nftables. |
| 145 | 212 |
func Enable() error {
|
| 146 | 213 |
enableOnce.Do(func() {
|
| ... | ... |
@@ -183,7 +250,7 @@ type table struct {
|
| 183 | 183 |
Name string |
| 184 | 184 |
Family Family |
| 185 | 185 |
|
| 186 |
- VMaps map[string]*vMap |
|
| 186 |
+ Maps map[string]*nftMap |
|
| 187 | 187 |
Sets map[string]*set |
| 188 | 188 |
Chains map[string]*chain |
| 189 | 189 |
|
| ... | ... |
@@ -225,7 +292,7 @@ func NewTable(family Family, name string) (Table, error) {
|
| 225 | 225 |
t: &table{
|
| 226 | 226 |
Name: name, |
| 227 | 227 |
Family: family, |
| 228 |
- VMaps: map[string]*vMap{},
|
|
| 228 |
+ Maps: map[string]*nftMap{},
|
|
| 229 | 229 |
Sets: map[string]*set{},
|
| 230 | 230 |
Chains: map[string]*chain{},
|
| 231 | 231 |
MustFlush: true, |
| ... | ... |
@@ -277,13 +344,13 @@ func (t Table) Family() Family {
|
| 277 | 277 |
// - add new map/set elements |
| 278 | 278 |
const incrementalUpdateTemplText = `{{$family := .Family}}{{$tableName := .Name}}
|
| 279 | 279 |
table {{$family}} {{$tableName}} {
|
| 280 |
- {{range .VMaps}}map {{.Name}} {
|
|
| 281 |
- type {{.ElementType}} : verdict
|
|
| 280 |
+ {{range .Maps}}map {{.Name}} {
|
|
| 281 |
+ {{.ElementTypeExpr}}
|
|
| 282 | 282 |
{{if len .Flags}}flags{{range .Flags}} {{.}}{{end}}{{end}}
|
| 283 | 283 |
} |
| 284 | 284 |
{{end}}
|
| 285 | 285 |
{{range .Sets}}set {{.Name}} {
|
| 286 |
- type {{.ElementType}}
|
|
| 286 |
+ {{.ElementTypeExpr}}
|
|
| 287 | 287 |
{{if len .Flags}}flags{{range .Flags}} {{.}}{{end}}{{end}}
|
| 288 | 288 |
} |
| 289 | 289 |
{{end}}
|
| ... | ... |
@@ -292,13 +359,13 @@ table {{$family}} {{$tableName}} {
|
| 292 | 292 |
} ; {{end}}{{end}}
|
| 293 | 293 |
} |
| 294 | 294 |
{{if .MustFlush}}flush table {{$family}} {{$tableName}}{{end}}
|
| 295 |
-{{range .VMaps}}{{if .MustFlush}}flush map {{$family}} {{$tableName}} {{.Name}}
|
|
| 295 |
+{{range .Maps}}{{if .MustFlush}}flush map {{$family}} {{$tableName}} {{.Name}}
|
|
| 296 | 296 |
{{end}}{{end}}
|
| 297 | 297 |
{{range .Sets}}{{if .MustFlush}}flush set {{$family}} {{$tableName}} {{.Name}}
|
| 298 | 298 |
{{end}}{{end}}
|
| 299 | 299 |
{{range .Chains}}{{if .MustFlush}}flush chain {{$family}} {{$tableName}} {{.Name}}
|
| 300 | 300 |
{{end}}{{end}}
|
| 301 |
-{{range .VMaps}}{{if .DeletedElements}}delete element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .DeletedElements}}{{$k}}, {{end}} }
|
|
| 301 |
+{{range .Maps}}{{if .DeletedElements}}delete element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .DeletedElements}}{{$k}}, {{end}} }
|
|
| 302 | 302 |
{{end}}{{end}}
|
| 303 | 303 |
{{range .Sets}}{{if .DeletedElements}}delete element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .DeletedElements}}{{$k}}, {{end}} }
|
| 304 | 304 |
{{end}}{{end}}
|
| ... | ... |
@@ -312,7 +379,7 @@ table {{$family}} {{$tableName}} {
|
| 312 | 312 |
} |
| 313 | 313 |
{{end}}{{end}}
|
| 314 | 314 |
} |
| 315 |
-{{range .VMaps}}{{if .AddedElements}}add element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .AddedElements}}{{$k}} : {{$v}}, {{end}} }
|
|
| 315 |
+{{range .Maps}}{{if .AddedElements}}add element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .AddedElements}}{{$k}} : {{$v}}, {{end}} }
|
|
| 316 | 316 |
{{end}}{{end}}
|
| 317 | 317 |
{{range .Sets}}{{if .AddedElements}}add element {{$family}} {{$tableName}} {{.Name}} { {{range $k,$v := .AddedElements}}{{$k}}, {{end}} }
|
| 318 | 318 |
{{end}}{{end}}
|
| ... | ... |
@@ -327,8 +394,8 @@ const reloadTemplText = `{{$family := .Family}}{{$tableName := .Name}}
|
| 327 | 327 |
table {{$family}} {{$tableName}} {}
|
| 328 | 328 |
delete table {{$family}} {{$tableName}}
|
| 329 | 329 |
table {{$family}} {{$tableName}} {
|
| 330 |
- {{range .VMaps}}map {{.Name}} {
|
|
| 331 |
- type {{.ElementType}} : verdict
|
|
| 330 |
+ {{range .Maps}}map {{.Name}} {
|
|
| 331 |
+ {{.ElementTypeExpr}}
|
|
| 332 | 332 |
{{if len .Flags}}flags{{range .Flags}} {{.}}{{end}}{{end}}
|
| 333 | 333 |
{{if .Elements}}elements = {
|
| 334 | 334 |
{{range $k,$v := .Elements}}{{$k}} : {{$v}},
|
| ... | ... |
@@ -337,7 +404,7 @@ table {{$family}} {{$tableName}} {
|
| 337 | 337 |
} |
| 338 | 338 |
{{end}}
|
| 339 | 339 |
{{range .Sets}}set {{.Name}} {
|
| 340 |
- type {{.ElementType}}
|
|
| 340 |
+ {{.ElementTypeExpr}}
|
|
| 341 | 341 |
{{if len .Flags}}flags{{range .Flags}} {{.}}{{end}}{{end}}
|
| 342 | 342 |
{{if .Elements}}elements = {
|
| 343 | 343 |
{{range $k,$v := .Elements}}{{$k}},
|
| ... | ... |
@@ -736,15 +803,15 @@ func (ru Rule) delete(ctx context.Context, t *table) (bool, error) {
|
| 736 | 736 |
} |
| 737 | 737 |
|
| 738 | 738 |
// //////////////////////////// |
| 739 |
-// VMaps |
|
| 739 |
+// Maps |
|
| 740 | 740 |
|
| 741 |
-// vMap is the internal representation of an nftables verdict map. |
|
| 741 |
+// nftMap is the internal representation of an nftables map (including verdict maps). |
|
| 742 | 742 |
// Its elements need to be exported for use by text/template, but they should only be |
| 743 | 743 |
// manipulated via exported methods. |
| 744 |
-type vMap struct {
|
|
| 744 |
+type nftMap struct {
|
|
| 745 | 745 |
table *table |
| 746 | 746 |
Name string |
| 747 |
- ElementType NftType |
|
| 747 |
+ ElementTypeExpr string |
|
| 748 | 748 |
Flags []string |
| 749 | 749 |
Elements map[string]string |
| 750 | 750 |
AddedElements map[string]string |
| ... | ... |
@@ -752,120 +819,120 @@ type vMap struct {
|
| 752 | 752 |
MustFlush bool |
| 753 | 753 |
} |
| 754 | 754 |
|
| 755 |
-// VMap implements the [Obj] interface, it can be passed to a |
|
| 756 |
-// [Modifier] to create or delete a verdict map. |
|
| 757 |
-type VMap struct {
|
|
| 755 |
+// Map implements the [Obj] interface, it can be passed to a |
|
| 756 |
+// [Modifier] to create or delete a map. |
|
| 757 |
+type Map struct {
|
|
| 758 | 758 |
Name string |
| 759 |
- ElementType NftType |
|
| 759 |
+ ElementType MapTyper |
|
| 760 | 760 |
Flags []string |
| 761 | 761 |
} |
| 762 | 762 |
|
| 763 |
-func (vm VMap) create(ctx context.Context, t *table) (bool, error) {
|
|
| 764 |
- if vm.Name == "" {
|
|
| 765 |
- return false, errors.New("vmap must have a name")
|
|
| 763 |
+func (m Map) create(ctx context.Context, t *table) (bool, error) {
|
|
| 764 |
+ if m.Name == "" {
|
|
| 765 |
+ return false, errors.New("map must have a name")
|
|
| 766 | 766 |
} |
| 767 |
- if _, ok := t.VMaps[vm.Name]; ok {
|
|
| 768 |
- return false, fmt.Errorf("vmap '%s' already exists", vm.Name)
|
|
| 767 |
+ if _, ok := t.Maps[m.Name]; ok {
|
|
| 768 |
+ return false, fmt.Errorf("map '%s' already exists", m.Name)
|
|
| 769 | 769 |
} |
| 770 |
- if vm.ElementType == "" {
|
|
| 771 |
- return false, fmt.Errorf("vmap '%s' has no element type", vm.Name)
|
|
| 770 |
+ if m.ElementType == nil {
|
|
| 771 |
+ return false, fmt.Errorf("map '%s' has no element type", m.Name)
|
|
| 772 | 772 |
} |
| 773 |
- v := &vMap{
|
|
| 773 |
+ nm := &nftMap{
|
|
| 774 | 774 |
table: t, |
| 775 |
- Name: vm.Name, |
|
| 776 |
- ElementType: vm.ElementType, |
|
| 777 |
- Flags: slices.Clone(vm.Flags), |
|
| 775 |
+ Name: m.Name, |
|
| 776 |
+ ElementTypeExpr: m.ElementType.mapType(), |
|
| 777 |
+ Flags: slices.Clone(m.Flags), |
|
| 778 | 778 |
Elements: map[string]string{},
|
| 779 | 779 |
AddedElements: map[string]string{},
|
| 780 | 780 |
DeletedElements: map[string]string{},
|
| 781 | 781 |
MustFlush: true, |
| 782 | 782 |
} |
| 783 |
- t.VMaps[v.Name] = v |
|
| 783 |
+ t.Maps[nm.Name] = nm |
|
| 784 | 784 |
log.G(ctx).WithFields(log.Fields{
|
| 785 | 785 |
"family": t.Family, |
| 786 | 786 |
"table": t.Name, |
| 787 |
- "vmap": v.Name, |
|
| 788 |
- }).Debug("nftables: created interface vmap")
|
|
| 787 |
+ "map": nm.Name, |
|
| 788 |
+ }).Debug("nftables: created map")
|
|
| 789 | 789 |
return true, nil |
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 |
-func (vm VMap) delete(ctx context.Context, t *table) (bool, error) {
|
|
| 793 |
- v := t.VMaps[vm.Name] |
|
| 794 |
- if v == nil {
|
|
| 795 |
- return false, fmt.Errorf("cannot delete vmap '%s', it does not exist", vm.Name)
|
|
| 792 |
+func (m Map) delete(ctx context.Context, t *table) (bool, error) {
|
|
| 793 |
+ nm := t.Maps[m.Name] |
|
| 794 |
+ if nm == nil {
|
|
| 795 |
+ return false, fmt.Errorf("cannot delete map '%s', it does not exist", m.Name)
|
|
| 796 | 796 |
} |
| 797 |
- if len(v.Elements) != 0 {
|
|
| 798 |
- return false, fmt.Errorf("cannot delete vmap '%s', it contains %d elements", v.Name, len(v.Elements))
|
|
| 797 |
+ if len(nm.Elements) != 0 {
|
|
| 798 |
+ return false, fmt.Errorf("cannot delete map '%s', it contains %d elements", nm.Name, len(nm.Elements))
|
|
| 799 | 799 |
} |
| 800 |
- delete(t.VMaps, v.Name) |
|
| 800 |
+ delete(t.Maps, nm.Name) |
|
| 801 | 801 |
t.DeleteCommands = append(t.DeleteCommands, |
| 802 |
- fmt.Sprintf("delete map %s %s %s", t.Family, t.Name, v.Name))
|
|
| 802 |
+ fmt.Sprintf("delete map %s %s %s", t.Family, t.Name, nm.Name))
|
|
| 803 | 803 |
log.G(ctx).WithFields(log.Fields{
|
| 804 | 804 |
"family": t.Family, |
| 805 | 805 |
"table": t.Name, |
| 806 |
- "vmap": v.Name, |
|
| 807 |
- }).Debug("nftables: deleted vmap")
|
|
| 806 |
+ "map": nm.Name, |
|
| 807 |
+ }).Debug("nftables: deleted map")
|
|
| 808 | 808 |
return true, nil |
| 809 | 809 |
} |
| 810 | 810 |
|
| 811 |
-// VMapElement implements the [Obj] interface, it can be passed to a |
|
| 812 |
-// [Modifier] to create or delete an entry in a verdict map. |
|
| 813 |
-type VMapElement struct {
|
|
| 814 |
- VmapName string |
|
| 815 |
- Key string |
|
| 816 |
- Verdict string |
|
| 811 |
+// MapElement implements the [Obj] interface, it can be passed to a |
|
| 812 |
+// [Modifier] to create or delete an entry in a map. |
|
| 813 |
+type MapElement struct {
|
|
| 814 |
+ MapName string |
|
| 815 |
+ Key string |
|
| 816 |
+ Value string |
|
| 817 | 817 |
} |
| 818 | 818 |
|
| 819 |
-func (ve VMapElement) create(ctx context.Context, t *table) (bool, error) {
|
|
| 820 |
- if ve.VmapName == "" {
|
|
| 821 |
- return false, errors.New("cannot add element to unnamed vmap")
|
|
| 819 |
+func (me MapElement) create(ctx context.Context, t *table) (bool, error) {
|
|
| 820 |
+ if me.MapName == "" {
|
|
| 821 |
+ return false, errors.New("cannot add element to unnamed map")
|
|
| 822 | 822 |
} |
| 823 |
- v := t.VMaps[ve.VmapName] |
|
| 824 |
- if v == nil {
|
|
| 825 |
- return false, fmt.Errorf("cannot add to vmap '%s', it does not exist", ve.VmapName)
|
|
| 823 |
+ nm := t.Maps[me.MapName] |
|
| 824 |
+ if nm == nil {
|
|
| 825 |
+ return false, fmt.Errorf("cannot add to map '%s', it does not exist", me.MapName)
|
|
| 826 | 826 |
} |
| 827 |
- if ve.Key == "" || ve.Verdict == "" {
|
|
| 828 |
- return false, fmt.Errorf("cannot add to vmap '%s', element must have key and verdict", ve.VmapName)
|
|
| 827 |
+ if me.Key == "" || me.Value == "" {
|
|
| 828 |
+ return false, fmt.Errorf("cannot add to map '%s', element must have key and value", me.MapName)
|
|
| 829 | 829 |
} |
| 830 |
- if _, ok := v.Elements[ve.Key]; ok {
|
|
| 831 |
- return false, fmt.Errorf("verdict map '%s' already contains element '%s'", ve.VmapName, ve.Key)
|
|
| 830 |
+ if _, ok := nm.Elements[me.Key]; ok {
|
|
| 831 |
+ return false, fmt.Errorf("map '%s' already contains element '%s'", me.MapName, me.Key)
|
|
| 832 | 832 |
} |
| 833 |
- v.Elements[ve.Key] = ve.Verdict |
|
| 834 |
- v.AddedElements[ve.Key] = ve.Verdict |
|
| 835 |
- delete(v.DeletedElements, ve.Key) |
|
| 833 |
+ nm.Elements[me.Key] = me.Value |
|
| 834 |
+ nm.AddedElements[me.Key] = me.Value |
|
| 835 |
+ delete(nm.DeletedElements, me.Key) |
|
| 836 | 836 |
log.G(ctx).WithFields(log.Fields{
|
| 837 |
- "family": t.Family, |
|
| 838 |
- "table": t.Name, |
|
| 839 |
- "vmap": ve.VmapName, |
|
| 840 |
- "key": ve.Key, |
|
| 841 |
- "verdict": ve.Verdict, |
|
| 842 |
- }).Debug("nftables: added vmap element")
|
|
| 837 |
+ "family": t.Family, |
|
| 838 |
+ "table": t.Name, |
|
| 839 |
+ "map": me.MapName, |
|
| 840 |
+ "key": me.Key, |
|
| 841 |
+ "value": me.Value, |
|
| 842 |
+ }).Debug("nftables: added map element")
|
|
| 843 | 843 |
return true, nil |
| 844 | 844 |
} |
| 845 | 845 |
|
| 846 |
-func (ve VMapElement) delete(ctx context.Context, t *table) (bool, error) {
|
|
| 847 |
- v := t.VMaps[ve.VmapName] |
|
| 848 |
- if v == nil {
|
|
| 849 |
- return false, fmt.Errorf("cannot delete from vmap '%s', it does not exist", ve.VmapName)
|
|
| 846 |
+func (me MapElement) delete(ctx context.Context, t *table) (bool, error) {
|
|
| 847 |
+ nm := t.Maps[me.MapName] |
|
| 848 |
+ if nm == nil {
|
|
| 849 |
+ return false, fmt.Errorf("cannot delete from map '%s', it does not exist", me.MapName)
|
|
| 850 | 850 |
} |
| 851 |
- oldVerdict, ok := v.Elements[ve.Key] |
|
| 851 |
+ oldValue, ok := nm.Elements[me.Key] |
|
| 852 | 852 |
if !ok {
|
| 853 |
- return false, fmt.Errorf("verdict map '%s' does not contain element '%s'", ve.VmapName, ve.Key)
|
|
| 853 |
+ return false, fmt.Errorf("map '%s' does not contain element '%s'", me.MapName, me.Key)
|
|
| 854 | 854 |
} |
| 855 |
- if oldVerdict != ve.Verdict {
|
|
| 856 |
- return false, fmt.Errorf("cannot delete verdict map '%s' element '%s', verdict was '%s', not '%s'",
|
|
| 857 |
- ve.VmapName, ve.Key, oldVerdict, ve.Verdict) |
|
| 855 |
+ if oldValue != me.Value {
|
|
| 856 |
+ return false, fmt.Errorf("cannot delete map '%s' element '%s', value was '%s', not '%s'",
|
|
| 857 |
+ me.MapName, me.Key, oldValue, me.Value) |
|
| 858 | 858 |
} |
| 859 |
- delete(v.Elements, ve.Key) |
|
| 860 |
- delete(v.AddedElements, ve.Key) |
|
| 861 |
- v.DeletedElements[ve.Key] = ve.Verdict |
|
| 859 |
+ delete(nm.Elements, me.Key) |
|
| 860 |
+ delete(nm.AddedElements, me.Key) |
|
| 861 |
+ nm.DeletedElements[me.Key] = me.Value |
|
| 862 | 862 |
log.G(ctx).WithFields(log.Fields{
|
| 863 |
- "family": t.Family, |
|
| 864 |
- "table": t.Name, |
|
| 865 |
- "vmap": ve.VmapName, |
|
| 866 |
- "key": ve.Key, |
|
| 867 |
- "verdict": ve.Verdict, |
|
| 868 |
- }).Debug("nftables: deleted vmap element")
|
|
| 863 |
+ "family": t.Family, |
|
| 864 |
+ "table": t.Name, |
|
| 865 |
+ "map": me.MapName, |
|
| 866 |
+ "key": me.Key, |
|
| 867 |
+ "value": me.Value, |
|
| 868 |
+ }).Debug("nftables: deleted map element")
|
|
| 869 | 869 |
return true, nil |
| 870 | 870 |
} |
| 871 | 871 |
|
| ... | ... |
@@ -878,7 +945,7 @@ func (ve VMapElement) delete(ctx context.Context, t *table) (bool, error) {
|
| 878 | 878 |
type set struct {
|
| 879 | 879 |
table *table |
| 880 | 880 |
Name string |
| 881 |
- ElementType NftType |
|
| 881 |
+ ElementTypeExpr string |
|
| 882 | 882 |
Flags []string |
| 883 | 883 |
Elements map[string]struct{}
|
| 884 | 884 |
AddedElements map[string]struct{}
|
| ... | ... |
@@ -890,7 +957,7 @@ type set struct {
|
| 890 | 890 |
// [Modifier] to create or delete a set. |
| 891 | 891 |
type Set struct {
|
| 892 | 892 |
Name string |
| 893 |
- ElementType NftType |
|
| 893 |
+ ElementType SetTyper |
|
| 894 | 894 |
Flags []string |
| 895 | 895 |
} |
| 896 | 896 |
|
| ... | ... |
@@ -902,14 +969,14 @@ func (sd Set) create(ctx context.Context, t *table) (bool, error) {
|
| 902 | 902 |
if _, ok := t.Sets[sd.Name]; ok {
|
| 903 | 903 |
return false, fmt.Errorf("set '%s' already exists", sd.Name)
|
| 904 | 904 |
} |
| 905 |
- if sd.ElementType == "" {
|
|
| 905 |
+ if sd.ElementType == nil {
|
|
| 906 | 906 |
return false, fmt.Errorf("set '%s' must have a type", sd.Name)
|
| 907 | 907 |
} |
| 908 | 908 |
s := &set{
|
| 909 | 909 |
table: t, |
| 910 | 910 |
Name: sd.Name, |
| 911 | 911 |
Elements: map[string]struct{}{},
|
| 912 |
- ElementType: sd.ElementType, |
|
| 912 |
+ ElementTypeExpr: sd.ElementType.setType(), |
|
| 913 | 913 |
Flags: slices.Clone(sd.Flags), |
| 914 | 914 |
AddedElements: map[string]struct{}{},
|
| 915 | 915 |
DeletedElements: map[string]struct{}{},
|
| ... | ... |
@@ -1041,7 +1108,7 @@ func (t *table) updatesApplied() {
|
| 1041 | 1041 |
for _, c := range t.Chains {
|
| 1042 | 1042 |
c.MustFlush = false |
| 1043 | 1043 |
} |
| 1044 |
- for _, m := range t.VMaps {
|
|
| 1044 |
+ for _, m := range t.Maps {
|
|
| 1045 | 1045 |
m.AddedElements = map[string]string{}
|
| 1046 | 1046 |
m.DeletedElements = map[string]string{}
|
| 1047 | 1047 |
m.MustFlush = false |
| ... | ... |
@@ -189,9 +189,9 @@ func TestVMap(t *testing.T) {
|
| 189 | 189 |
|
| 190 | 190 |
// Create a verdict map. |
| 191 | 191 |
const mapName = "this_is_a_vmap" |
| 192 |
- tm.Create(VMap{Name: mapName, ElementType: NftTypeIfname})
|
|
| 193 |
- tm.Create(VMapElement{VmapName: mapName, Key: "eth0", Verdict: "return"})
|
|
| 194 |
- tm.Create(VMapElement{VmapName: mapName, Key: "eth1", Verdict: "drop"})
|
|
| 192 |
+ tm.Create(Map{Name: mapName, ElementType: Ifname.VMap()})
|
|
| 193 |
+ tm.Create(MapElement{MapName: mapName, Key: "eth0", Value: "return"})
|
|
| 194 |
+ tm.Create(MapElement{MapName: mapName, Key: "eth1", Value: "drop"})
|
|
| 195 | 195 |
|
| 196 | 196 |
// Update nftables and check what happened. |
| 197 | 197 |
applyAndCheck(t, tbl, tm, t.Name()+"/created.golden") |
| ... | ... |
@@ -217,10 +217,10 @@ func TestSet(t *testing.T) {
|
| 217 | 217 |
// Create a set in each table. |
| 218 | 218 |
const set4Name = "set4" |
| 219 | 219 |
tm4 := Modifier{}
|
| 220 |
- tm4.Create(Set{Name: set4Name, ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}})
|
|
| 220 |
+ tm4.Create(Set{Name: set4Name, ElementType: IPv4Addr, Flags: []string{"interval"}})
|
|
| 221 | 221 |
const set6Name = "set6" |
| 222 | 222 |
tm6 := Modifier{}
|
| 223 |
- tm6.Create(Set{Name: set6Name, ElementType: NftTypeIPv6Addr, Flags: []string{"interval"}})
|
|
| 223 |
+ tm6.Create(Set{Name: set6Name, ElementType: IPv6Addr, Flags: []string{"interval"}})
|
|
| 224 | 224 |
|
| 225 | 225 |
// Add elements to each set. |
| 226 | 226 |
tm4.Create(SetElement{SetName: set4Name, Element: "192.0.2.0/24"})
|
| ... | ... |
@@ -256,12 +256,12 @@ func TestReload(t *testing.T) {
|
| 256 | 256 |
tm.Create(Rule{Chain: bcName, Group: 0, Rule: []string{"counter"}})
|
| 257 | 257 |
|
| 258 | 258 |
const vmapName = "this_is_a_vmap" |
| 259 |
- tm.Create(VMap{Name: vmapName, ElementType: NftTypeIfname})
|
|
| 260 |
- tm.Create(VMapElement{VmapName: vmapName, Key: "eth0", Verdict: "return"})
|
|
| 261 |
- tm.Create(VMapElement{VmapName: vmapName, Key: "eth1", Verdict: "return"})
|
|
| 259 |
+ tm.Create(Map{Name: vmapName, ElementType: Ifname.VMap()})
|
|
| 260 |
+ tm.Create(MapElement{MapName: vmapName, Key: "eth0", Value: "return"})
|
|
| 261 |
+ tm.Create(MapElement{MapName: vmapName, Key: "eth1", Value: "return"})
|
|
| 262 | 262 |
|
| 263 | 263 |
const setName = "this_is_a_set" |
| 264 |
- tm.Create(Set{Name: setName, ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}})
|
|
| 264 |
+ tm.Create(Set{Name: setName, ElementType: IPv4Addr, Flags: []string{"interval"}})
|
|
| 265 | 265 |
tm.Create(SetElement{SetName: setName, Element: "192.0.2.0/24"})
|
| 266 | 266 |
|
| 267 | 267 |
applyAndCheck(t, tbl, tm, t.Name()+"/created.golden") |
| ... | ... |
@@ -463,110 +463,110 @@ func TestValidation(t *testing.T) {
|
| 463 | 463 |
}, |
| 464 | 464 |
expErr: "chain 'achain', cannot add empty rule", |
| 465 | 465 |
}, |
| 466 |
- // VMap |
|
| 466 |
+ // Map (verdict) |
|
| 467 | 467 |
{
|
| 468 |
- name: "duplicate vmap", |
|
| 468 |
+ name: "duplicate map", |
|
| 469 | 469 |
cmds: []command{
|
| 470 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 471 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 470 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 471 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 472 | 472 |
}, |
| 473 |
- expErr: "vmap 'avmap' already exists", |
|
| 473 |
+ expErr: "map 'avmap' already exists", |
|
| 474 | 474 |
}, |
| 475 | 475 |
{
|
| 476 |
- name: "delete nonexistent vmap", |
|
| 476 |
+ name: "delete nonexistent map", |
|
| 477 | 477 |
cmds: []command{
|
| 478 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}, delete: true},
|
|
| 478 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}, delete: true},
|
|
| 479 | 479 |
}, |
| 480 |
- expErr: "cannot delete vmap 'avmap', it does not exist", |
|
| 480 |
+ expErr: "cannot delete map 'avmap', it does not exist", |
|
| 481 | 481 |
}, |
| 482 | 482 |
{
|
| 483 |
- name: "missing vmap name", |
|
| 484 |
- cmds: []command{{obj: VMap{ElementType: NftTypeIfname}}},
|
|
| 485 |
- expErr: "vmap must have a name", |
|
| 483 |
+ name: "missing map name", |
|
| 484 |
+ cmds: []command{{obj: Map{ElementType: Ifname.VMap()}}},
|
|
| 485 |
+ expErr: "map must have a name", |
|
| 486 | 486 |
}, |
| 487 | 487 |
{
|
| 488 |
- name: "missing vmap element type", |
|
| 489 |
- cmds: []command{{obj: VMap{Name: "avmap"}}},
|
|
| 490 |
- expErr: "vmap 'avmap' has no element type", |
|
| 488 |
+ name: "missing map element type", |
|
| 489 |
+ cmds: []command{{obj: Map{Name: "avmap"}}},
|
|
| 490 |
+ expErr: "map 'avmap' has no element type", |
|
| 491 | 491 |
}, |
| 492 | 492 |
{
|
| 493 |
- name: "delete non-empty vmap", |
|
| 493 |
+ name: "delete non-empty map", |
|
| 494 | 494 |
cmds: []command{
|
| 495 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 496 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0", Verdict: "drop"}},
|
|
| 497 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}, delete: true},
|
|
| 495 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 496 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0", Value: "drop"}},
|
|
| 497 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}, delete: true},
|
|
| 498 | 498 |
}, |
| 499 |
- expErr: "cannot delete vmap 'avmap', it contains 1 elements", |
|
| 499 |
+ expErr: "cannot delete map 'avmap', it contains 1 elements", |
|
| 500 | 500 |
}, |
| 501 |
- // VMapElement |
|
| 501 |
+ // MapElement |
|
| 502 | 502 |
{
|
| 503 |
- name: "duplicate vmap element", |
|
| 503 |
+ name: "duplicate map element", |
|
| 504 | 504 |
cmds: []command{
|
| 505 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 506 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0", Verdict: "drop"}},
|
|
| 507 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0", Verdict: "drop"}},
|
|
| 505 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 506 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0", Value: "drop"}},
|
|
| 507 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0", Value: "drop"}},
|
|
| 508 | 508 |
}, |
| 509 |
- expErr: "verdict map 'avmap' already contains element 'eth0'", |
|
| 509 |
+ expErr: "map 'avmap' already contains element 'eth0'", |
|
| 510 | 510 |
}, |
| 511 | 511 |
{
|
| 512 |
- name: "add to vmap that does not exist", |
|
| 512 |
+ name: "add to map that does not exist", |
|
| 513 | 513 |
cmds: []command{
|
| 514 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0", Verdict: "drop"}},
|
|
| 514 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0", Value: "drop"}},
|
|
| 515 | 515 |
}, |
| 516 |
- expErr: "cannot add to vmap 'avmap', it does not exist", |
|
| 516 |
+ expErr: "cannot add to map 'avmap', it does not exist", |
|
| 517 | 517 |
}, |
| 518 | 518 |
{
|
| 519 |
- name: "delete nonexistent vmap element", |
|
| 519 |
+ name: "delete nonexistent map element", |
|
| 520 | 520 |
cmds: []command{
|
| 521 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 522 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0", Verdict: "drop"}, delete: true},
|
|
| 521 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 522 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0", Value: "drop"}, delete: true},
|
|
| 523 | 523 |
}, |
| 524 |
- expErr: "verdict map 'avmap' does not contain element 'eth0'", |
|
| 524 |
+ expErr: "map 'avmap' does not contain element 'eth0'", |
|
| 525 | 525 |
}, |
| 526 | 526 |
{
|
| 527 |
- name: "vmap element with no named vmap", |
|
| 527 |
+ name: "map element with no named map", |
|
| 528 | 528 |
cmds: []command{
|
| 529 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 530 |
- {obj: VMapElement{Key: "eth0", Verdict: "drop"}},
|
|
| 529 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 530 |
+ {obj: MapElement{Key: "eth0", Value: "drop"}},
|
|
| 531 | 531 |
}, |
| 532 |
- expErr: "cannot add element to unnamed vmap", |
|
| 532 |
+ expErr: "cannot add element to unnamed map", |
|
| 533 | 533 |
}, |
| 534 | 534 |
{
|
| 535 |
- name: "vmap element with no key", |
|
| 535 |
+ name: "map element with no key", |
|
| 536 | 536 |
cmds: []command{
|
| 537 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 538 |
- {obj: VMapElement{VmapName: "avmap", Verdict: "drop"}},
|
|
| 537 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 538 |
+ {obj: MapElement{MapName: "avmap", Value: "drop"}},
|
|
| 539 | 539 |
}, |
| 540 |
- expErr: "cannot add to vmap 'avmap', element must have key and verdict", |
|
| 540 |
+ expErr: "cannot add to map 'avmap', element must have key and value", |
|
| 541 | 541 |
}, |
| 542 | 542 |
{
|
| 543 |
- name: "vmap element with no verdict", |
|
| 543 |
+ name: "map element with no value", |
|
| 544 | 544 |
cmds: []command{
|
| 545 |
- {obj: VMap{Name: "avmap", ElementType: NftTypeIfname}},
|
|
| 546 |
- {obj: VMapElement{VmapName: "avmap", Key: "eth0"}},
|
|
| 545 |
+ {obj: Map{Name: "avmap", ElementType: Ifname.VMap()}},
|
|
| 546 |
+ {obj: MapElement{MapName: "avmap", Key: "eth0"}},
|
|
| 547 | 547 |
}, |
| 548 |
- expErr: "cannot add to vmap 'avmap', element must have key and verdict", |
|
| 548 |
+ expErr: "cannot add to map 'avmap', element must have key and value", |
|
| 549 | 549 |
}, |
| 550 | 550 |
// Set |
| 551 | 551 |
{
|
| 552 | 552 |
name: "duplicate set", |
| 553 | 553 |
cmds: []command{
|
| 554 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 555 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 554 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 555 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 556 | 556 |
}, |
| 557 | 557 |
expErr: "set 'aset' already exists", |
| 558 | 558 |
}, |
| 559 | 559 |
{
|
| 560 | 560 |
name: "delete nonexistent set", |
| 561 | 561 |
cmds: []command{
|
| 562 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}, delete: true},
|
|
| 562 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}, delete: true},
|
|
| 563 | 563 |
}, |
| 564 | 564 |
expErr: "cannot delete set 'aset', it does not exist", |
| 565 | 565 |
}, |
| 566 | 566 |
{
|
| 567 | 567 |
name: "missing set name", |
| 568 | 568 |
cmds: []command{
|
| 569 |
- {obj: Set{ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 569 |
+ {obj: Set{ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 570 | 570 |
}, |
| 571 | 571 |
expErr: "set must have a name", |
| 572 | 572 |
}, |
| ... | ... |
@@ -580,9 +580,9 @@ func TestValidation(t *testing.T) {
|
| 580 | 580 |
{
|
| 581 | 581 |
name: "delete non-empty set", |
| 582 | 582 |
cmds: []command{
|
| 583 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 583 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 584 | 584 |
{obj: SetElement{SetName: "aset", Element: "192.0.2.0/24"}},
|
| 585 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}, delete: true},
|
|
| 585 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}, delete: true},
|
|
| 586 | 586 |
}, |
| 587 | 587 |
expErr: "cannot delete set 'aset', it contains 1 elements", |
| 588 | 588 |
}, |
| ... | ... |
@@ -590,7 +590,7 @@ func TestValidation(t *testing.T) {
|
| 590 | 590 |
{
|
| 591 | 591 |
name: "duplicate set element", |
| 592 | 592 |
cmds: []command{
|
| 593 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 593 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 594 | 594 |
{obj: SetElement{SetName: "aset", Element: "192.0.2.0/24"}},
|
| 595 | 595 |
{obj: SetElement{SetName: "aset", Element: "192.0.2.0/24"}},
|
| 596 | 596 |
}, |
| ... | ... |
@@ -599,7 +599,7 @@ func TestValidation(t *testing.T) {
|
| 599 | 599 |
{
|
| 600 | 600 |
name: "delete nonexistent set element", |
| 601 | 601 |
cmds: []command{
|
| 602 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 602 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 603 | 603 |
{obj: SetElement{SetName: "aset", Element: "192.0.2.0/24"}, delete: true},
|
| 604 | 604 |
}, |
| 605 | 605 |
expErr: "cannot delete '192.0.2.0/24' from set 'aset', it does not exist", |
| ... | ... |
@@ -607,7 +607,7 @@ func TestValidation(t *testing.T) {
|
| 607 | 607 |
{
|
| 608 | 608 |
name: "add set element to unnamed set", |
| 609 | 609 |
cmds: []command{
|
| 610 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 610 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 611 | 611 |
{obj: SetElement{Element: "192.0.2.0/24"}},
|
| 612 | 612 |
}, |
| 613 | 613 |
expErr: "cannot add to set '', it does not exist", |
| ... | ... |
@@ -615,7 +615,7 @@ func TestValidation(t *testing.T) {
|
| 615 | 615 |
{
|
| 616 | 616 |
name: "add set element with no element", |
| 617 | 617 |
cmds: []command{
|
| 618 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 618 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 619 | 619 |
{obj: SetElement{SetName: "aset"}},
|
| 620 | 620 |
}, |
| 621 | 621 |
expErr: "cannot add to set 'aset', element not specified", |
| ... | ... |
@@ -623,7 +623,7 @@ func TestValidation(t *testing.T) {
|
| 623 | 623 |
{
|
| 624 | 624 |
name: "mismatched set element type", |
| 625 | 625 |
cmds: []command{
|
| 626 |
- {obj: Set{Name: "aset", ElementType: NftTypeIPv4Addr, Flags: []string{"interval"}}},
|
|
| 626 |
+ {obj: Set{Name: "aset", ElementType: IPv4Addr, Flags: []string{"interval"}}},
|
|
| 627 | 627 |
{obj: SetElement{SetName: "aset", Element: "2001:db8::/64"}},
|
| 628 | 628 |
}, |
| 629 | 629 |
expErr: "Address family for hostname not supported", |