-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Pod secondary interfaces on VLAN network #5365
Conversation
// Include the inner veth interface name in the name generation, as one Pod can have more | ||
// than one interfaces inc. secondary interfaces, while the outer interface name must be | ||
// be unique. | ||
hostIfaceName := util.GenerateContainerOuterVethName(podName, podNamespace, containerID, containerIfaceName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that "inner veth" is usually referred to as containerVeth
and the "outer veth" referred to as hostVeth
. The CNI project seems to be using this terminology (https://github.com/containernetworking/plugins/blob/v1.3.0/pkg/ip/link_linux.go#L139).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to containerVeth and hostVeth.
pkg/agent/cniserver/secondary.go
Outdated
} | ||
hostIface := result.Interfaces[0] | ||
containerIface := result.Interfaces[1] | ||
klog.InfoS("Configured SR-IOV interface", "Pod", podName, "Namespace", podNamespace, "interface", containerInterfaceName, "hostInterface", hostIface) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use klog.KRef
(or klog.KObj
when appropriate) to log references to K8s objects:
klog.InfoS("Configured SR-IOV interface", "Pod", klog.KRef(podNamespace, podName), "interface", containerInterfaceName, "hostInterface", hostIface)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
const ( | ||
sriovNetworkType = "sriov" | ||
vlanNetworkType = "vlan" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we create a dedicated type
for this?
type NetworkType string
const (
sriovNetworkType NetworkType = "sriov"
vlanNetworkType NetworkType = "vlan"
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a type.
@@ -38,5 +39,7 @@ type SecondaryNetworkConfig struct { | |||
Type string `json:"type,omitempty"` | |||
// Set networkType to "sriov" | |||
NetworkType string `json:"networkType,omitempty"` | |||
MTU int `json:"mtu, omitempty"` | |||
VLAN uint16 `json:"vlan, omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably better to use int32
in a public API, especially since the max value is 4096 and you have to perform validation anyway
even though this is not a K8s API: https://github.com/zecke/Kubernetes/blob/master/docs/devel/api-conventions.md#primitive-types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to int32
@@ -38,5 +39,7 @@ type SecondaryNetworkConfig struct { | |||
Type string `json:"type,omitempty"` | |||
// Set networkType to "sriov" | |||
NetworkType string `json:"networkType,omitempty"` | |||
MTU int `json:"mtu, omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/int/int32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if cniType != "" { | ||
configStr = strings.Replace(configStr, "type\": \"antrea", "type\": \""+cniType, 1) | ||
} | ||
configStr = strings.Replace(configStr, "mtu\": 1500", "mtu\": "+strconv.Itoa(mtu), 1) | ||
configStr = strings.Replace(configStr, "vlan\": 100", "vlan\": "+strconv.Itoa(int(vlan)), 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, you should use the text/template
package to do this more cleanly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to text/template
. Thanks for the suggestion.
CNIConfig: config2, | ||
}, | ||
} | ||
assert.True(t, reflect.DeepEqual(&savedCNIConfig, infos[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought assert.Equal
already used reflect.DeepEqual
to check for comparison?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. Changed to use assert.Equal
.
fb2bd0c
to
c5f19c5
Compare
} | ||
|
||
// ConfigureSriovSecondaryInterface configures a SR-IOV secondary interface for a Pod. | ||
func (pc *podConfigurator) ConfigureSriovSecondaryInterface( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This func is copied from the original cniserver/sriov.go without changes.
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package podwatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All funcs in this file are moved from podwatch/controller.go without changes.
// Include the inner veth interface name in the name generation, as one Pod can have more | ||
// than one interfaces inc. secondary interfaces, while the outer interface name must be | ||
// be unique. | ||
hostIfaceName := util.GenerateContainerOuterVethName(podName, podNamespace, containerID, containerIfaceName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to containerVeth and hostVeth.
@@ -38,5 +39,7 @@ type SecondaryNetworkConfig struct { | |||
Type string `json:"type,omitempty"` | |||
// Set networkType to "sriov" | |||
NetworkType string `json:"networkType,omitempty"` | |||
MTU int `json:"mtu, omitempty"` | |||
VLAN uint16 `json:"vlan, omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to int32
@@ -38,5 +39,7 @@ type SecondaryNetworkConfig struct { | |||
Type string `json:"type,omitempty"` | |||
// Set networkType to "sriov" | |||
NetworkType string `json:"networkType,omitempty"` | |||
MTU int `json:"mtu, omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if cniType != "" { | ||
configStr = strings.Replace(configStr, "type\": \"antrea", "type\": \""+cniType, 1) | ||
} | ||
configStr = strings.Replace(configStr, "mtu\": 1500", "mtu\": "+strconv.Itoa(mtu), 1) | ||
configStr = strings.Replace(configStr, "vlan\": 100", "vlan\": "+strconv.Itoa(int(vlan)), 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to text/template
. Thanks for the suggestion.
CNIConfig: config2, | ||
}, | ||
} | ||
assert.True(t, reflect.DeepEqual(&savedCNIConfig, infos[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. Changed to use assert.Equal
.
5db5adf
to
39a71fc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only a couple of nits, otherwise LGTM
pkg/agent/util/net.go
Outdated
// The probability of collision should be neglectable. | ||
func GenerateContainerInterfaceName(podName, podNamespace, containerID string) string { | ||
// Use the podName as the prefix and the containerID as the hashing key. | ||
// podNamespace is not used currently. | ||
return generateInterfaceName(containerID, podName, true) | ||
} | ||
|
||
// GenerateContainerOuterVethName generates a unique interface name using the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/GenerateContainerOuterVethName/GenerateContainerHostVethName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
pkg/agent/util/net_test.go
Outdated
assert.True(t, len(ifaceName0) <= interfaceNameLength) | ||
assert.True(t, strings.HasPrefix(ifaceName0, podName0+"-")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use require
as you typically want all the subtests below to be skipped if one of these assertions is false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pkg/agent/util/net_test.go
Outdated
containerID0 := "container0" | ||
eth0 := "eth0" | ||
ifaceName0 := GenerateContainerHostVethName(podName0, podNamespace0, containerID0, eth0) | ||
assert.True(t, len(ifaceName0) <= interfaceNameLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require.Less
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
continue | ||
} | ||
if networkConfig.NetworkType == vlanNetworkType { | ||
if networkConfig.VLAN > vlanIDMax || networkConfig.VLAN < 0 { | ||
klog.ErrorS(nil, "Invalid VLAN ID", "NetworkAttachmentDefinition", klog.KObj(netDefCRD), "Pod", klog.KObj(pod)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe add the VLAN value to the log
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
} | ||
if networkConfig.MTU < 0 { | ||
klog.ErrorS(nil, "Invalid MTU", "NetworkAttachmentDefinition", klog.KObj(netDefCRD), "Pod", klog.KObj(pod)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, but for MTU
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
network2 := testNetwork("net2") | ||
savedCNIConfig := *cniConfig | ||
network1 := testNetwork("net1", sriovNetworkType) | ||
network2 := testNetworkExt("net2", "", vlanNetworkType, defaultMTU, 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: define a local constant for the vlan id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
This commit adds support for connecting Pod secondary interfaces to a VLAN network. A Pod secondary interface configured with the VLAN networkType will be connected to the secondary network OVS bridge, and the specified VLAN tag will be set on the OVS port. This commit mostly follows the existing SR-IOV secondary network implementation, in which a Pod controller configures Pod secondary interfaces based on the local Pod events. It thus inherits the existing limitations, like secondary interface configuration is not persisted on the Node and may get lost after antrea-agent restarts. Signed-off-by: Jianjun Shen <shenj@vmware.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/test-all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes LGTM. thank you @jianjuns
This commit adds support for connecting Pod secondary interfaces to a VLAN network. A Pod secondary interface configured with the VLAN networkType will be connected to the secondary network OVS bridge, and the specified VLAN tag will be set on the OVS port.
This commit mostly follows the existing SR-IOV secondary network implementation, in which a Pod controller configures Pod secondary interfaces based on the local Pod events. It thus inherits the existing limitations, like secondary interface configuration is not persisted on the Node and may get lost after antrea-agent restarts.
Reorganize some files:
Renamed pkg/agent/cniserver/sriov.go to secondary.go, and put secondary interface configuration funcs there.
Move SR-IOV interface related code in pkg/agent/secondarynetwork/podwatch/controller.go to sriov.go.
Issue: #5278