portmap: support hairpin, improve performance

This change improves the performance of the portmap plugin and fixes
hairpin, when a container is mapped back to itself.

Performance is improved by using a multiport test to reduce rule
traversal, and by using a masquerade mark.

Hairpin is fixed by enabling masquerading for hairpin traffic.
This commit is contained in:
Casey Callendrello
2017-11-03 16:53:12 +00:00
parent 7f98c94613
commit 5576f3120e
8 changed files with 513 additions and 296 deletions

View File

@ -47,10 +47,12 @@ type PortMapEntry struct {
type PortMapConf struct {
types.NetConf
SNAT *bool `json:"snat,omitempty"`
ConditionsV4 *[]string `json:"conditionsV4"`
ConditionsV6 *[]string `json:"conditionsV6"`
RuntimeConfig struct {
SNAT *bool `json:"snat,omitempty"`
ConditionsV4 *[]string `json:"conditionsV4"`
ConditionsV6 *[]string `json:"conditionsV6"`
MarkMasqBit *int `json:"markMasqBit"`
ExternalSetMarkChain *string `json:"externalSetMarkChain"`
RuntimeConfig struct {
PortMaps []PortMapEntry `json:"portMappings,omitempty"`
} `json:"runtimeConfig,omitempty"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
@ -63,6 +65,10 @@ type PortMapConf struct {
ContIPv6 net.IP `json:"-"`
}
// The default mark bit to signal that masquerading is required
// Kubernetes uses 14 and 15, Calico uses 20-31.
const DefaultMarkBit = 13
func cmdAdd(args *skel.CmdArgs) error {
netConf, err := parseConfig(args.StdinData, args.IfName)
if err != nil {
@ -145,6 +151,19 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
conf.SNAT = &tvar
}
if conf.MarkMasqBit != nil && conf.ExternalSetMarkChain != nil {
return nil, fmt.Errorf("Cannot specify externalSetMarkChain and markMasqBit")
}
if conf.MarkMasqBit == nil {
bvar := DefaultMarkBit // go constants are "special"
conf.MarkMasqBit = &bvar
}
if *conf.MarkMasqBit < 0 || *conf.MarkMasqBit > 31 {
return nil, fmt.Errorf("MasqMarkBit must be between 0 and 31")
}
// Reject invalid port numbers
for _, pm := range conf.RuntimeConfig.PortMaps {
if pm.ContainerPort <= 0 {