1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
// Copyright 2021 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ports
// Flags represents the type of port reservation.
//
// +stateify savable
type Flags struct {
// MostRecent represents UDP SO_REUSEADDR.
MostRecent bool
// LoadBalanced indicates SO_REUSEPORT.
//
// LoadBalanced takes precidence over MostRecent.
LoadBalanced bool
// TupleOnly represents TCP SO_REUSEADDR.
TupleOnly bool
}
// Bits converts the Flags to their bitset form.
func (f Flags) Bits() BitFlags {
var rf BitFlags
if f.MostRecent {
rf |= MostRecentFlag
}
if f.LoadBalanced {
rf |= LoadBalancedFlag
}
if f.TupleOnly {
rf |= TupleOnlyFlag
}
return rf
}
// Effective returns the effective behavior of a flag config.
func (f Flags) Effective() Flags {
e := f
if e.LoadBalanced && e.MostRecent {
e.MostRecent = false
}
return e
}
// BitFlags is a bitset representation of Flags.
type BitFlags uint32
const (
// MostRecentFlag represents Flags.MostRecent.
MostRecentFlag BitFlags = 1 << iota
// LoadBalancedFlag represents Flags.LoadBalanced.
LoadBalancedFlag
// TupleOnlyFlag represents Flags.TupleOnly.
TupleOnlyFlag
// nextFlag is the value that the next added flag will have.
//
// It is used to calculate FlagMask below. It is also the number of
// valid flag states.
nextFlag
// FlagMask is a bit mask for BitFlags.
FlagMask = nextFlag - 1
// MultiBindFlagMask contains the flags that allow binding the same
// tuple multiple times.
MultiBindFlagMask = MostRecentFlag | LoadBalancedFlag
)
// ToFlags converts the bitset into a Flags struct.
func (f BitFlags) ToFlags() Flags {
return Flags{
MostRecent: f&MostRecentFlag != 0,
LoadBalanced: f&LoadBalancedFlag != 0,
TupleOnly: f&TupleOnlyFlag != 0,
}
}
// FlagCounter counts how many references each flag combination has.
type FlagCounter struct {
// refs stores the count for each possible flag combination, (0 though
// FlagMask).
refs [nextFlag]int
}
// AddRef increases the reference count for a specific flag combination.
func (c *FlagCounter) AddRef(flags BitFlags) {
c.refs[flags]++
}
// DropRef decreases the reference count for a specific flag combination.
func (c *FlagCounter) DropRef(flags BitFlags) {
c.refs[flags]--
}
// TotalRefs calculates the total number of references for all flag
// combinations.
func (c FlagCounter) TotalRefs() int {
var total int
for _, r := range c.refs {
total += r
}
return total
}
// FlagRefs returns the number of references with all specified flags.
func (c FlagCounter) FlagRefs(flags BitFlags) int {
var total int
for i, r := range c.refs {
if BitFlags(i)&flags == flags {
total += r
}
}
return total
}
// AllRefsHave returns if all references have all specified flags.
func (c FlagCounter) AllRefsHave(flags BitFlags) bool {
for i, r := range c.refs {
if BitFlags(i)&flags != flags && r > 0 {
return false
}
}
return true
}
// SharedFlags returns the set of flags shared by all references.
func (c FlagCounter) SharedFlags() BitFlags {
intersection := FlagMask
for i, r := range c.refs {
if r > 0 {
intersection &= BitFlags(i)
}
}
return intersection
}
|