]>
Commit | Line | Data |
---|---|---|
2dc7590d BP |
1 | #! @PYTHON@ |
2 | ||
3 | import os | |
4 | import re | |
5 | import stat | |
6 | import sys | |
7 | ||
8 | if "--help" in sys.argv: | |
9 | sys.stdout.write("""\ | |
10 | ovs-check-dead-ifs: Check for packet sockets for nonexistent network devices. | |
11 | ||
12 | One side effect of the "force-reload-kmod" command that reloads the | |
13 | Open vSwitch kernel module is that all the network devices that the | |
14 | Open vSwitch kernel module implemented get destroyed and then replaced | |
15 | by new instances with the same names. Unfortunately, programs that | |
16 | are listening for packets on the original network devices will not | |
17 | receive packets that arrive on the new instances. This causes some | |
18 | services, such as DHCP, to silently fail. This program looks for such | |
19 | problems and, if it finds any, prints information about programs that | |
20 | are in such a state. The system administrator should then take some | |
21 | action to fix the problem, such as restarting these programs. | |
22 | """) | |
23 | sys.exit(0) | |
24 | elif len(sys.argv) > 1: | |
25 | sys.stderr.write("ovs-check-dead-ifs: no arguments or options accepted " | |
26 | "(use --help for help)\n") | |
27 | sys.exit(1) | |
28 | ||
29 | # Get the set of all valid ifindexes. | |
30 | # | |
31 | # 0 is always valid for our purposes because it means "any interface". | |
32 | valid_ifindexes = set([]) | |
33 | for ifname in os.listdir("/sys/class/net"): | |
34 | fn = "/sys/class/net/%s/ifindex" % ifname | |
35 | try: | |
36 | valid_ifindexes.add(int(open(fn).readline())) | |
37 | except IOError: | |
38 | pass | |
39 | except ValueError: | |
40 | print "%s: unexpected format\n" % fn | |
41 | ||
42 | # Get inodes for all packet sockets whose ifindexes don't exist. | |
43 | invalid_inodes = set() | |
44 | f = open("/proc/net/packet") | |
45 | f.readline() # Skip header line. | |
46 | for line in f: | |
47 | fields = line.split() | |
48 | ifindex = int(fields[4]) | |
49 | if ifindex not in valid_ifindexes: | |
50 | invalid_inodes.add(int(fields[8])) | |
51 | f.close() | |
52 | ||
53 | if not invalid_inodes: | |
54 | sys.exit(0) | |
55 | ||
56 | # Now find the processes that are using those packet sockets. | |
57 | inode_re = re.compile(r'socket:\[([0-9]+)\]$') | |
58 | bad_pids = set() | |
59 | for pid in os.listdir("/proc"): | |
60 | try: | |
61 | pid = int(pid) | |
62 | except ValueError: | |
63 | continue | |
64 | ||
65 | for fd in os.listdir("/proc/%d/fd" % pid): | |
66 | try: | |
67 | fd = int(fd) | |
68 | except ValueError: | |
69 | continue | |
70 | ||
71 | try: | |
72 | s = os.stat("/proc/%d/fd/%d" % (pid, fd)) | |
73 | except OSError: | |
74 | continue | |
75 | ||
76 | if not stat.S_ISSOCK(s.st_mode): | |
77 | continue | |
78 | ||
79 | try: | |
80 | linkname = os.readlink("/proc/%d/fd/%d" % (pid, fd)) | |
81 | except OSError: | |
82 | continue | |
83 | ||
84 | m = inode_re.match(linkname) | |
85 | if not m: | |
86 | continue | |
87 | ||
88 | inode = int(m.group(1)) | |
89 | if inode in invalid_inodes: | |
90 | bad_pids.add(pid) | |
91 | ||
92 | if bad_pids: | |
93 | print """ | |
94 | The following processes are listening for packets to arrive on network devices | |
95 | that no longer exist. You may want to restart them.""" | |
96 | os.execvp("ps", ["ps"] + ["%s" % pid for pid in bad_pids]) |