-
Notifications
You must be signed in to change notification settings - Fork 25
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
don't down interface #5
Comments
i've changed terminate function in tuncer to tunctl:persist(FD, true).
|
hm, but when we start application tcpdump shows traffic but half the time |
@alexshavelev sorry I didn't see this issue! Which OS are you using? |
centos 7 |
@alexshavelev commenting out down/1 and persist/2 should've worked. I'll run some tests and check out what is going on. About the persist flag being reset on terminate, that is probably a bug. Will take a look. |
After applying the fix you suggested to persist the interface after
tuncer shuts down, I can see what is going on:
~~~ erlang
% $ ip addr show dev test0
% Device "test0" does not exist.
{ok, T} = tuncer:create(<<"test0">>).
% $ ip addr show dev test0
% 11: test0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 500
% link/ether 6e:87:44:1f:6d:b3 brd ff:ff:ff:ff:ff:ff
% inet 10.10.0.3/8 brd 10.255.255.255 scope global test0
% valid_lft forever preferred_lft forever
tuncer:up(T, "10.10.0.3").
tuncer:setopt(T, {active, true}).
tuncer:persist(T, true).
tuncer:getfd(T). % fd 13
% $ ip addr show dev test0
% 12: test0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
% link/ether b2:6b:d0:63:ed:19 brd ff:ff:ff:ff:ff:ff
% inet 10.10.0.3/8 brd 10.255.255.255 scope global test0
% valid_lft forever preferred_lft forever
% inet6 fe80::b06b:d0ff:fe63:ed19/64 scope link
% valid_lft forever preferred_lft forever
flush().
% {tuntap, ..., ...}
exit(T, kill).
{ok, T1} = tuncer:create(<<"test0">>).
** exception exit: {badmatch,{error,ebusy}}
procket:read(13, 1). % returns {ok, <<255>>}
procket:close(13). % ok
{ok, T1} = tuncer:create(<<"test0">>). % works!
~~~
So under some circumstances the terminate callback of the tuncer
gen_server isn't called, leaving the tuntap fd open.
One workaround might be to store the fd number and close it:
~~~ erlang
{ok, T} = tuncer:create(<<"test0">>),
FD = tuncer:getfd(T),
procket:close(FD).
~~~
The fix will probably require adding a function to procket that stores
the fd as an NIF resource. When the fd resource goes out of scope,
the NIF will close the fd.
Some other bugs to fix:
* `tuncer:up/2`: "ip addr show tap0" displays the interface status as
UNKNOWN instead of UP
* `tuncer:create(<<"test">>, [{active,true}])` returns `{error, einval}`
* add `tuncer:up/1`, similar to "ifconfig tap0 up" for already configured
devices
I'll fix these over the next few days. Thanks for reporting this bug!
~~~
diff --git a/src/tuncer.erl b/src/tuncer.erl
index 6733cac..5c0cc78 100644
--- a/src/tuncer.erl
+++ b/src/tuncer.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2016, Michael Santos <[email protected]>
+%% Copyright (c) 2011-2017, Michael Santos <[email protected]>
%% All rights reserved.
%%
%% Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,8 @@
pid, % PID of controlling process
fd, % TUN/TAP file descriptor
dev, % device name
- flag % TUNSETIFF ifr flags
+ flag, % TUNSETIFF ifr flags
+ persist
}).
-define(IFNAMSIZ, 16).
@@ -254,7 +255,7 @@ handle_call({recv, _Len}, _From, State) ->
handle_call({persist, Status}, _From, #state{fd = FD} = State) ->
Reply = tunctl:persist(FD, Status),
- {reply, Reply, State};
+ {reply, Reply, State#state{persist = Status}};
handle_call({owner, Owner}, _From, #state{fd = FD} = State) ->
Reply = tunctl:owner(FD, Owner),
@@ -290,10 +291,15 @@ handle_info({'EXIT',_,normal}, State) ->
handle_info({'EXIT', _, _}, #state{port = false} = State) ->
{noreply, State};
…-handle_info({'EXIT', Port, Error}, #state{port = Port, pid = Pid, fd = FD, dev = Dev} = State) ->
+handle_info({'EXIT', Port, Error}, #state{port = Port, pid = Pid, fd = FD, dev = Dev, persist = Persist} = State) ->
Pid ! {tuntap_error, self(), Error},
- _ = tunctl:down(Dev),
- tunctl:persist(FD, false),
+ case Persist of
+ true ->
+ ok;
+ false ->
+ _ = tunctl:down(Dev),
+ tunctl:persist(FD, false)
+ end,
procket:close(FD),
{stop, normal, State};
~~~
|
If the caller has set the tuntap interface to persistent, do not destroy or unconfigure the interface on shutdown as suggested by @alexshavelev in #5
for example we have two interfaces:
eth1 and tap2.
we connect to eth1 via ewpcap, work and than use ewpcap:close. after interface is still up.
after we restart application which works with tap2 via tunctl we need every type to up interface manually like 'ifup tap2'. it's not useful to make it via tunctl:up, because application works on different nodes and we need custom configs with ips for interfaces.
is there any possibility to keep interface up? if we delete call of '_ = tunctl:down(Dev),' or 'procket:close(FD)' interface is up, but we get 'ebusy' error
The text was updated successfully, but these errors were encountered: