Skip to content
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

Add new ipip backend #842

Merged
merged 2 commits into from
Dec 13, 2017
Merged

Add new ipip backend #842

merged 2 commits into from
Dec 13, 2017

Conversation

chenchun
Copy link
Contributor

Signed-off-by: forrestchen forrestchen@tencent.com
Signed-off-by: Chun Chen ramichen@tencent.com

@ChenLingPeng

Copy link
Contributor

@tomdee tomdee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution! I've taken a quick look and I have a few comments. I'll take a more thorough look next week.

Could you also add IPIP to the end to end tests. It should be as simple as just adding a few lines like this to https://github.com/coreos/flannel/blob/master/dist/functional-test.sh#L88 and to functional-test-k8s.sh

}

func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backend, error) {
if !extIface.ExtAddr.Equal(extIface.IfaceAddr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you want this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an environment to test this and currently removed this check.


const (
backendType = "ipip"
tunnelName = "tunl0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vxlan uses flannel.<VNI> for the tunnel device and UDP uses flannel0 I think it would be good if IPIP also used flannel in the tunnel device name. Maybe just flannel.ipip

Copy link
Contributor Author

@chenchun chenchun Oct 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using tunl0 device, created a new flanneld.ipip ipip device. As a effect of this we should set flanneld.ipip‘s local ip to public ip, or kernel will forward packets to tunl0.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand your comment about setting the IP address for flanneld.ipip to the public. Could you explain some more?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tunl0 is an namespace default device with IPIP attributes local=any and remote=any.
If we create another IPIP device flannel.ipip with local=any and remote=any. It seems when receiving IPIP protocol packets, kernel will forward them to tunl0 as a fallback device instead of flannel.ipip. See https://github.com/torvalds/linux/blob/master/net/ipv4/ip_tunnel.c#L85-L96 .

So we have two options here, either rename tunl0 to flannel.ipip or setting local attribute of flannel.ipip to distinguish these two devices. Considering tunl0 might be used by user, so I choose the later option.

const (
backendType = "ipip"
tunnelName = "tunl0"
tunnelMaxMTU = 1480
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have a maximum MTU?

Copy link
Contributor Author

@chenchun chenchun Oct 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made 1480 as a default MTU and made MTU configurable.

@@ -115,4 +115,5 @@ IPIP kind of tunnels is the simplest one. It has the lowest overhead, but can in

Type:
* `Type` (string): `ipip`
* `MTU` (number): The mtu of ipip device. Defaults to 1480.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write a little more here to help guide users. Why is this this value? Why and when would a user want to change it? And what value would they change it to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -110,6 +116,12 @@ test_udp_perf() {
perf
}

test_ipip_perf() {
write_config_etcd ipip
create_ping_dest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@tomdee
Copy link
Contributor

tomdee commented Oct 28, 2017

I added a few more comments (including this one which might be hidden #842 (comment))

@chenchun chenchun force-pushed the iptun branch 3 times, most recently from fb2550f to 399f1ce Compare November 1, 2017 01:13
@chenchun
Copy link
Contributor Author

chenchun commented Nov 9, 2017

@tomdee PTAL

@@ -0,0 +1,176 @@
// Copyright 2015 flannel authors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the copyright lines to 2017 please.

@tomdee
Copy link
Contributor

tomdee commented Nov 10, 2017

Hi @chenchun I want to make sure I understand the design for this fully before merging it. If I understand your comment (#842 (comment)) and the code correctly then you're not setting a "remote" but you are setting the "local" address to the public IP. Can you confirm what effects this has? Which address will be used as the source IP address for packets that originate from the host network namespace? And what if the public IP isn't the same as an IP address on the host, then you can't actually use it?

I also have some questions about the MTU settings. On the vxlan backend, the vxlan tunnel device is associated with a physical ethernet device on the host. This is what is used to determine the MTU value to use. Flanneld will always have an interface that it chooses (specified with the --iface option), so maybe you should be getting the MTU value from that device? WDYT?

So maybe the best option would be to "local" address to the address of the interface that flannel selects and also use that as the for the MTU?

@tomdee
Copy link
Contributor

tomdee commented Nov 10, 2017

When I run your code I'm seeing two IPIP devices, is that expected?

6: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
7: flannel.ipip@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/ipip 192.168.5.188 brd 0.0.0.0

@tomdee
Copy link
Contributor

tomdee commented Nov 10, 2017

Also, one final request: Would you mind adding some comments to your code explain why it's written like it is. For some examples of the style, see the vxlan code - e.g. https://github.com/coreos/flannel/blob/master/backend/vxlan/device.go#L108

@chenchun
Copy link
Contributor Author

If I understand your comment (#842 (comment)) and the code correctly then you're not setting a "remote" but you are setting the "local" address to the public IP. Can you confirm what effects this has? Which address will be used as the source IP address for packets that originate from the host network namespace? And what if the public IP isn't the same as an IP address on the host, then you can't actually use it?

My mistake. I originally had a check if PublicIP is the same as IfaceAddr and I assumed they are equal. Now that I removed this check, I will change the "local" address to the IfaceAddr.

if !extIface.ExtAddr.Equal(extIface.IfaceAddr) {
		return nil, fmt.Errorf("your PublicIP differs from interface IP, meaning that probably you're on a NAT, which is not supported by host-gw backend")
	}

maybe you should be getting the MTU value from that device? WDYT?

I agree.

When I run your code I'm seeing two IPIP devices, is that expected?

Yes, this is expected. tunl0 is created by the ipip kernel module itself and it is not used by this ipip backend.

@chenchun
Copy link
Contributor Author

The last update removed MTU param from backend configuration. We may not need it since we calculate it based on --iface device's MTU.

}

// Don't set remote attribute making flannel.ipip an one to many tunnel device.
if (ipip.Local != nil && !ipip.Local.Equal(be.extIface.IfaceAddr)) || (ipip.Remote != nil && ipip.Remote.String() != "0.0.0.0") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that just returning an error here is good enough. If there's a flannel.ipip that isn't an ipip device then it wasn't created by flannel, so in that case it's best to just return an error. But in this case, the local address can change between flannel restarts, so flannel should be able to recreate the device and not just return an error. You should follow similar logic to vxlan (see the ensureLink function), it should delete and recreate the device if the config changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

oldMTU := link.Attrs().MTU
if oldMTU > expectMTU || oldMTU == 0 {
glog.Infof("current MTU of %s is %d, setting it to %d", tunnelName, oldMTU, expectMTU)
err := netlink.LinkSetMTU(link, expectMTU)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to explicitly set the link to down first?

Copy link
Contributor Author

@chenchun chenchun Nov 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find any reference that saying setting down the link first. I think changing MTU on the fly is ok.

From http://linux-ip.net/html/tools-ip-link.html

B.3.5. Using ip link set to change the MTU

The remaining options to the ip link command cannot be used while the interface is in an UP state.

return nil, fmt.Errorf("failed to set %v UP: %v", tunnelName, err)
}

existingAddrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this next section of code is identical to the vxlan code, could you extract the code into a common package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -0,0 +1,216 @@
// Copyright 2017 flannel authors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much of this file is the same as the host-gw code. It would be great if the common code could be pulled out (and then it could be shared by the vxlan code too but I would do that in a followup PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to do it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added RouteNetwork in common.go.

@tomdee
Copy link
Contributor

tomdee commented Nov 24, 2017

Hi @chenchun I've looked at this code some more and realized how similar so much of is it to existing flannel code. It would be great to refactor and pull out the common code.

A few other things that need to happen before this can be released (but not necessarily before this PR is merged)

  • Documentation update (maybe in the troubleshooting guide too) to descrieb that the tunl0 device will be created but that's not a bug (!) - users will get confused about this.
  • a ..._windows.go stub needs to be created.
  • Some manual functional and scale testing.

@chenchun chenchun force-pushed the iptun branch 5 times, most recently from 517827a to 0444147 Compare November 30, 2017 14:07
@chenchun chenchun force-pushed the iptun branch 3 times, most recently from efadee3 to df5617a Compare December 1, 2017 12:14
ChenLingPeng and others added 2 commits December 10, 2017 14:54
Signed-off-by: forrestchen <forrestchen@tencent.com>
Signed-off-by: Chun Chen <ramichen@tencent.com>

IPIP backend update

- Rename ipip device to flannel.ipip
- Add tests for ipip backend
- Add mtu config to ipip backend
- Fix invalid use of EEXIST
- Remove the equal check of `IfaceAddr` and `ExtAddr`
- Set MTU to 20 less than the MTU of the selected iface (specified with the --iface option)

Update according to the review

- Recreate flannel.ipip device if local address changes
- Add `EnsureV4AddressOnLink`
- Update ipip document to describe that the tunl0 device will be created but that's not a bug

Merge hostgw network with ipip network
@tomdee
Copy link
Contributor

tomdee commented Dec 13, 2017

@chenchun and @ChenLingPeng I rebased and squashed your commits and added another commit to the PR just to make some small markups. Your original commits are at https://github.com/tomdee/flannel/tree/iptun-orig if you still want them.

@tomdee tomdee merged commit 9ac5988 into flannel-io:master Dec 13, 2017
@chenchun
Copy link
Contributor Author

Ausome! Thanks for making this happen.

@chenchun chenchun deleted the iptun branch January 13, 2018 02:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants