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

net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC #53482

Closed
MaoJianwei opened this issue Jun 21, 2022 · 17 comments

Comments

@MaoJianwei
Copy link
Contributor

MaoJianwei commented Jun 21, 2022

Hi, team,

What version of Go are you using (go version)?

$ go version
go version go1.18.3 linux/amd64

Does this issue reproduce with the latest release?

Yes, it is.

What operating system and processor architecture are you using (go env)?

Ubuntu 20.04

What did you do?

I inspect the flags of an Interface object to check if this NIC is up and in running state.

	intfs, _ := net.Interfaces()
	for _, intf := range intfs {
		log.Printf("NIC name: %s, flags: %s\n", intf.Name, intf.Flags)
		if intf.Flags & net.FlagUp != 0 {
			// I expect this interface 'intf' is up and in running state, but it is not.
		}
	}

But, althought some NIC(s) have the FlagUp flag, when I check again by ip addr | grep state, I found they are in DOWN state actually.

The situation is: there is no fiber or twisted-pair cable plugged in the NIC, and I run ip link set XXX up to set it up administratively and manually.

Environment:

  1. I manually set the NICs(ens1f0/eno1/ens1f1/eno2/eno3) up for administrative purpose, leave the NICs(ens2f0,ens2f1) down without any operation. And, there is no cable/fiber plugged in them.
  2. The NIC(eno4) is plugged, and it is automatically up.

The output of ip addr | grep state, please pay attention to the state DOWN words:

XXX@XXX:~# ip addr | grep state
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: ens1f0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
3: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
4: ens1f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
5: eno2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
6: eno3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
7: eno4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
8: ens2f0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default qlen 1000
9: ens2f1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default qlen 1000
10: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default

What did you expect to see?

I expect to see NICs(ens1f0/eno1/ens1f1/eno2/eno3) and NICs(ens2f0,ens2f1) are all down, and only NIC(eno4) is up.

What did you see instead?

I actually see NICs(ens1f0/eno1/ens1f1/eno2/eno3) and NIC(eno4) are up, and NICs(ens2f0,ens2f1) are down, the output of the above snippet program is as follow:
Please pay attention to the flags: up words.

2022/06/21 20:56:49 NIC name: lo, flags: up|loopback
2022/06/21 20:56:49 NIC name: ens1f0, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: eno1, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: ens1f1, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: eno2, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: eno3, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: eno4, flags: up|broadcast|multicast
2022/06/21 20:56:49 NIC name: ens2f0, flags: broadcast|multicast
2022/06/21 20:56:49 NIC name: ens2f1, flags: broadcast|multicast
2022/06/21 20:56:49 NIC name: docker0, flags: up|broadcast|multicast

In conclusion

We can't distinguish the state of a NIC through only the FlagUp flag in the following situations:

  1. interface is plugged, automatically up, and in running(UP) state
  2. interface is not plugged, administratively or manually set to up, but in DOWN state

I have fixed this bug, and will send a pull request soon :)

I add a new flag to exactly reflect the states of an interface or NIC, as the title says.

And I get the right and exact report as the follow output, you can see only NIC(lo/eno4) are reported in running state:
Please pay attention to the tailing running word.

2022/06/21 21:01:52 NIC name: lo, flags: up|loopback|running
2022/06/21 21:01:52 NIC name: ens1f0, flags: up|broadcast|multicast
2022/06/21 21:01:52 NIC name: eno1, flags: up|broadcast|multicast
2022/06/21 21:01:52 NIC name: ens1f1, flags: up|broadcast|multicast
2022/06/21 21:01:52 NIC name: eno2, flags: up|broadcast|multicast
2022/06/21 21:01:52 NIC name: eno3, flags: up|broadcast|multicast
2022/06/21 21:01:52 NIC name: eno4, flags: up|broadcast|multicast|running
2022/06/21 21:01:52 NIC name: ens2f0, flags: broadcast|multicast
2022/06/21 21:01:52 NIC name: ens2f1, flags: broadcast|multicast
2022/06/21 21:01:52 NIC name: docker0, flags: up|broadcast|multicast

In another words, the NIC(s) which only have up flag but no running flag, are set up administratively or manually.

Thanks,
Mao

MaoJianwei added a commit to MaoJianwei/go that referenced this issue Jun 21, 2022
…lect the states of an interface or NIC.

And a new flag(FlagRunning), and correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up, but in DOWN state
So, We can't distinguish the state of a NIC through the FlagUp flag only.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
@gopherbot
Copy link

Change https://go.dev/cl/413454 mentions this issue: net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC.

MaoJianwei added a commit to MaoJianwei/go that referenced this issue Jun 21, 2022
…lect the states of an interface or NIC.

And a new flag(FlagRunning), and correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up, but in DOWN state
So, We can't distinguish the state of a NIC through the FlagUp flag only.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
@ianlancetaylor ianlancetaylor changed the title net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC. proposal: net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC Jun 21, 2022
@gopherbot gopherbot added this to the Proposal milestone Jun 21, 2022
@ianlancetaylor
Copy link
Contributor

Turning this issue into a proposal.

@ianlancetaylor ianlancetaylor added this to Incoming in Proposals (old) Jun 21, 2022
@MaoJianwei
Copy link
Contributor Author

I see you have marked the issue as a proposal, thanks @ianlancetaylor .
What do I need to do, or just need to wait for weekly proposal review meetings to pick it to be active proposal? :)

@rsc
Copy link
Contributor

rsc commented Jun 22, 2022

I'm a little confused about inventing a new flag that does not appear in the ip addr output. Specifically:

6: eno3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
7: eno4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000

The problem seems to be that we want to distinguish eno3 and eno4, where both have the UP flag set but one is 'state DOWN' and the other is 'state UP'. So the suggestion is to add a new flag RUNNING that means 'state UP'.

Is 'RUNNING' the right name for that? Is there a RUNNING bit on other systems that it might collide with?

@MaoJianwei
Copy link
Contributor Author

MaoJianwei commented Jun 23, 2022

Hi, @rsc ,

You get the core problem correctly, thanks :)

There are three reasons to choose the 'RUNNING' name:

  1. The flag of an interface for its real up/down state is parsed from the syscall result, that is corresponding to the $go/src/net/interface_linux.go: linkFlags() function and the $go/src/syscall/zerrors_linux_amd64.go: const IFF_RUNNING flag. In other words, the existed constant flag was named 'IFF_RUNNING', so I just inherit the 'RUNNING' name here in this proposal.
  2. The flag of an interface for the administrative UP is already named 'FlagUp', so in order to distinguish with it, I choose the 'FlagRunning' name.
  3. the linkFlags() function and the 'IFF_RUNNING' flag are adopted by some systems and architectures, not only linux/amd64, as follow:

linkFlags() function:

$go/src/net/interface_linux.go
$go/src/net/interface_aix.go
$go/src/net/interface_bsd.go
$go/src/net/interface_solaris.go

'IFF_RUNNING' flag, constant:

$go/src/syscall/zerrors_linux_amd64.go
$go/src/syscall/zerrors_openbsd_arm64.go
$go/src/syscall/zerrors_linux_riscv64.go
$go/src/syscall/zerrors_linux_s390x.go
$go/src/syscall/zerrors_netbsd_386.go
$go/src/syscall/zerrors_aix_ppc64.go
... ...

This flag is defined in more than 30+ *.go files.
We can easily check out this situation by double-press shift
in the Goland IDE and search it.

'IFF_DRV_RUNNING' flag, the meaning is same as 'IFF_RUNNING':

$go/src/syscall/zerrors_freebsd_amd64.go
$go/src/syscall/zerrors_freebsd_arm64.go
$go/src/syscall/zerrors_freebsd_arm.go
$go/src/syscall/zerrors_freebsd_386.go

So, in my opinion, it is good to choose the RUNNING and FlagRunning name for this proposal :)

Thanks,
Mao

@rsc
Copy link
Contributor

rsc commented Jun 29, 2022

Just to confirm: it sounds like the ip addr program is reporting the kernel IFF_RUNNING bit when it prints 'state UP' (bit is set) or 'state DOWN' (bit is clear). Is that correct? (Certainly weird if so.)

What bit is it reporting when it says 'state UNKNOWN' like in the very first comment's:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000

?

Also, looking at PR #53484, does Windows ever distinguish UP from RUNNING? Do we need to do something more precise there?

@MaoJianwei
Copy link
Contributor Author

MaoJianwei commented Jun 29, 2022

Hi, @rsc

Yes, that is correct and reasonable.

Just to confirm:
it sounds like the ip addr program is reporting the kernel IFF_RUNNING bit when it prints 'state UP' (bit is set) or 'state DOWN' (bit is clear).
Is that correct? (Certainly weird if so.)

For the lo(loopback) interface, it report state UNKNOWN with IFF_RUNNING bit is set, because loopback is always UP and RUNNING.

What bit is it reporting when it says 'state UNKNOWN' like in the very first comment's:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000

Windows doesn't distinguish UP from RUNNING, so we don't need to do more things, it is ok to sync the UP & RUNNING state.

does Windows ever distinguish UP from RUNNING? Do we need to do something more precise there?

Thanks,
Mao

@rsc rsc moved this from Incoming to Active in Proposals (old) Jul 1, 2022
@rsc
Copy link
Contributor

rsc commented Jul 1, 2022

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc
Copy link
Contributor

rsc commented Jul 13, 2022

Sounds like the bit exists and is called Running, so adding it here should be uncontroversial.

@rsc
Copy link
Contributor

rsc commented Jul 13, 2022

Based on the discussion above, this proposal seems like a likely accept.
— rsc for the proposal review group

@rsc rsc moved this from Active to Likely Accept in Proposals (old) Jul 13, 2022
@MaoJianwei
Copy link
Contributor Author

MaoJianwei commented Jul 14, 2022

Sounds like the bit exists and is called Running, so adding it here should be uncontroversial.

Yes, the bit is right here, and we want to provide it to everyone for using :)

Thanks,
Mao

@rsc rsc moved this from Likely Accept to Accepted in Proposals (old) Jul 20, 2022
@rsc
Copy link
Contributor

rsc commented Jul 20, 2022

No change in consensus, so accepted. 🎉
This issue now tracks the work of implementing the proposal.
— rsc for the proposal review group

@rsc rsc changed the title proposal: net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC net: add FlagRunning to the Flags of struct Interface, to exactly reflect the states of an interface or NIC Jul 20, 2022
@rsc rsc modified the milestones: Proposal, Backlog Jul 20, 2022
@MaoJianwei
Copy link
Contributor Author

MaoJianwei commented Jul 25, 2022

Many thanks, wish the code will continue to be reviewed :)
@ianlancetaylor @neild @rsc

https://go-review.googlesource.com/c/go/+/413454

Github pull request: #53484

MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 25, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up, but in DOWN state
So, We can't distinguish the state of a NIC through the FlagUp flag only.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 25, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up, but in DOWN state
So, We can't distinguish the state of a NIC through the FlagUp flag only.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 25, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up, but in DOWN state
So, We can't distinguish the state of a NIC through the FlagUp flag only.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 26, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up,
but in DOWN state

So, We can't distinguish the state of a NIC by the FlagUp flag alone.

Fixes golang#53482

Signed-off-by: Jianwei Mao <maojianwei2012@126.com>
MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 26, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up,
but in DOWN state

So, We can't distinguish the state of a NIC by the FlagUp flag alone.

Fixes golang#53482
MaoJianwei added a commit to MaoJianwei/go that referenced this issue Aug 26, 2022
Correctly set this flag while parsing the syscall result.

The FlagUp flag can not distinguish the following situations:
1. interface is plugged, automatically up, and in running(UP) state
2. interface is not plugged, administratively or manually set to up,
but in DOWN state

So, We can't distinguish the state of a NIC by the FlagUp flag alone.

Fixes golang#53482
@MaoJianwei
Copy link
Contributor Author

Hi, @ianlancetaylor and @rsc , many thanks for your help, this PR has finally merged :)

Will this commit be automatically released in Go 1.20 ?
It was merged into the master branch, but has not marked with Go1.20 Milestone yet.

Cheers,
Mao

@seankhliao
Copy link
Member

yes, everything in master goes into the next release

@seankhliao seankhliao modified the milestones: Backlog, Go1.20 Aug 27, 2022
@MaoJianwei
Copy link
Contributor Author

Thanks, @seankhliao :)

@gopherbot
Copy link

Change https://go.dev/cl/451420 mentions this issue: doc/go1.20: add release notes for net package

gopherbot pushed a commit that referenced this issue Nov 18, 2022
For #50101
For #51152
For #53482
For #55301
For #56515

Change-Id: I11edeb4be0a7f80fb72fd7680a3407d081f83b8b
Reviewed-on: https://go-review.googlesource.com/c/go/+/451420
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Damien Neil <dneil@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
@golang golang locked and limited conversation to collaborators Nov 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

5 participants