Repository: containernetworking/cni
Pull request #1041 (2023-11-20 09:08:04)

Add route attributes - MTU, AdvMSS, Priority
Extend route attributes to make route selection available based on route priority and enable per-route MTU settings.
It's will be helpfull in multi-CNI environment, and networks, that support jumbo-frame.

Fixes: #1004



Patch:
diff --git a/SPEC.md b/SPEC.md
index 0fec14f..4d1a862 100644
--- a/SPEC.md
+++ b/SPEC.md
@@ -536,6 +536,9 @@ Plugins must output a JSON object with the following keys upon a successful `ADD
 - `routes`: Routes created by this attachment:
     - `dst`: The destination of the route, in CIDR notation
     - `gw`: The next hop address. If unset, a value in `gateway` in the `ips` array may be used.
+    - `mtu` (uint): The MTU (Maximum transmission unit) along the path to the destination.
+    - `advmss` (uint): The MSS (Maximal Segment Size) to advertise to these destinations when establishing TCP connections.
+    - `priority` (uint): The priority of route, lower is higher.
 - `dns`: a dictionary consisting of DNS configuration information
     - `nameservers` (list of strings): list of a priority-ordered list of DNS nameservers that this network is aware of. Each entry in the list is a string containing either an IPv4 or an IPv6 address.
     - `domain` (string): the local domain used for short hostname lookups.
diff --git a/pkg/skel/skel.go b/pkg/skel/skel.go
index d592f1b..432923d 100644
--- a/pkg/skel/skel.go
+++ b/pkg/skel/skel.go
@@ -245,7 +245,7 @@ func (t *dispatcher) pluginMain(funcs CNIFuncs, versionInfo version.PluginInfo,
 		if err != nil {
 			return err
 		}
-		if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" && cmdArgs.NetnsOverride != "1" {
+		if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" || cmdArgs.NetnsOverride != "1" {
 			isPluginNetNS, checkErr := ns.CheckNetNS(cmdArgs.Netns)
 			if checkErr != nil {
 				return checkErr
@@ -280,7 +280,7 @@ func (t *dispatcher) pluginMain(funcs CNIFuncs, versionInfo version.PluginInfo,
 		if err != nil {
 			return err
 		}
-		if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" && cmdArgs.NetnsOverride != "1" {
+		if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" || cmdArgs.NetnsOverride != "1" {
 			isPluginNetNS, checkErr := ns.CheckNetNS(cmdArgs.Netns)
 			if checkErr != nil {
 				return checkErr
diff --git a/pkg/types/types.go b/pkg/types/types.go
index 62ee748..2c12d73 100644
--- a/pkg/types/types.go
+++ b/pkg/types/types.go
@@ -129,8 +129,11 @@ func (d *DNS) Copy() *DNS {
 }
 
 type Route struct {
-	Dst net.IPNet
-	GW  net.IP
+	Dst      net.IPNet
+	GW       net.IP
+	MTU      int
+	AdvMSS   int
+	Priority int
 }
 
 func (r *Route) String() string {
@@ -143,8 +146,11 @@ func (r *Route) Copy() *Route {
 	}
 
 	return &Route{
-		Dst: r.Dst,
-		GW:  r.GW,
+		Dst:      r.Dst,
+		GW:       r.GW,
+		MTU:      r.MTU,
+		AdvMSS:   r.AdvMSS,
+		Priority: r.Priority,
 	}
 }
 
@@ -195,8 +201,11 @@ func (e *Error) Print() error {
 
 // JSON (un)marshallable types
 type route struct {
-	Dst IPNet  `json:"dst"`
-	GW  net.IP `json:"gw,omitempty"`
+	Dst      IPNet  `json:"dst"`
+	GW       net.IP `json:"gw,omitempty"`
+	MTU      int    `json:"mtu,omitempty"`
+	AdvMSS   int    `json:"advmss,omitempty"`
+	Priority int    `json:"priority,omitempty"`
 }
 
 func (r *Route) UnmarshalJSON(data []byte) error {
@@ -207,13 +216,20 @@ func (r *Route) UnmarshalJSON(data []byte) error {
 
 	r.Dst = net.IPNet(rt.Dst)
 	r.GW = rt.GW
+	r.MTU = rt.MTU
+	r.AdvMSS = rt.AdvMSS
+	r.Priority = rt.Priority
+
 	return nil
 }
 
 func (r Route) MarshalJSON() ([]byte, error) {
 	rt := route{
-		Dst: IPNet(r.Dst),
-		GW:  r.GW,
+		Dst:      IPNet(r.Dst),
+		GW:       r.GW,
+		MTU:      r.MTU,
+		AdvMSS:   r.AdvMSS,
+		Priority: r.Priority,
 	}
 
 	return json.Marshal(rt)


Test patch:
diff --git a/pkg/types/types_test.go b/pkg/types/types_test.go
index 4fed4a6..ee0a829 100644
--- a/pkg/types/types_test.go
+++ b/pkg/types/types_test.go
@@ -87,14 +87,17 @@ var _ = Describe("Types", func() {
 					IP:   net.ParseIP("1.2.3.0"),
 					Mask: net.CIDRMask(24, 32),
 				},
-				GW: net.ParseIP("1.2.3.1"),
+				GW:       net.ParseIP("1.2.3.1"),
+				MTU:      1500,
+				AdvMSS:   1340,
+				Priority: 100,
 			}
 		})
 
 		It("marshals and unmarshals to JSON", func() {
 			jsonBytes, err := json.Marshal(example)
 			Expect(err).NotTo(HaveOccurred())
-			Expect(jsonBytes).To(MatchJSON(`{ "dst": "1.2.3.0/24", "gw": "1.2.3.1" }`))
+			Expect(jsonBytes).To(MatchJSON(`{ "dst": "1.2.3.0/24", "gw": "1.2.3.1", "mtu": 1500, "advmss": 1340, "priority": 100 }`))
 
 			var unmarshaled types.Route
 			Expect(json.Unmarshal(jsonBytes, &unmarshaled)).To(Succeed())
@@ -110,7 +113,7 @@ var _ = Describe("Types", func() {
 		})
 
 		It("formats as a string with a hex mask", func() {
-			Expect(example.String()).To(Equal(`{Dst:{IP:1.2.3.0 Mask:ffffff00} GW:1.2.3.1}`))
+			Expect(example.String()).To(Equal(`{Dst:{IP:1.2.3.0 Mask:ffffff00} GW:1.2.3.1 MTU:1500 AdvMSS:1340 Priority:100}`))
 		})
 	})