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

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

Open
MaoJianwei opened this issue Jun 21, 2022 · 5 comments · May be fixed by #53484
Labels
Projects
Milestone

Comments

@MaoJianwei
Copy link

@MaoJianwei 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

@gopherbot gopherbot commented Jun 21, 2022

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

@ianlancetaylor ianlancetaylor commented Jun 21, 2022

Turning this issue into a proposal.

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

@MaoJianwei MaoJianwei commented Jun 22, 2022

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 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
Author

@MaoJianwei 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Proposals
Incoming
4 participants