* More or less completed the network notification module - it does not remove

old invalid user listeners yet, though (ie. if a team dies).
* Implemented userland network monitor functions.
* Added a few notifications to the network stack, even though this part isn't
  complete yet (especially notify_interface_changed()).
* Added optional debug output to the notifications module.
* Added the module to the image, it basically works now (tested).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28825 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-12-27 20:48:28 +00:00
parent 2e71ef292f
commit d68ffdedc0
10 changed files with 179 additions and 44 deletions
+4 -3
View File
@@ -138,12 +138,12 @@ BEOS_ADD_ONS_DRIVERS_GRAPHICS = $(X86_ONLY)radeon $(X86_ONLY)nvidia
$(X86_ONLY)s3 $(X86_ONLY)vesa #$(X86_ONLY)via #$(X86_ONLY)vmware $(X86_ONLY)s3 $(X86_ONLY)vesa #$(X86_ONLY)via #$(X86_ONLY)vmware
; ;
BEOS_ADD_ONS_DRIVERS_MIDI = emuxki ; BEOS_ADD_ONS_DRIVERS_MIDI = emuxki ;
BEOS_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)broadcom440x BEOS_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)broadcom440x
$(X86_ONLY)broadcom570x etherpci $(X86_ONLY)ipro1000 $(X86_ONLY)broadcom570x etherpci $(X86_ONLY)ipro1000
pegasus $(X86_ONLY)rtl8139 rtl8169 $(X86_ONLY)rtl81xx sis900 pegasus $(X86_ONLY)rtl8139 rtl8169 $(X86_ONLY)rtl81xx sis900
$(X86_ONLY)via_rhine wb840 $(X86_ONLY)ipro100 $(X86_ONLY)nforce $(X86_ONLY)via_rhine wb840 $(X86_ONLY)ipro100 $(X86_ONLY)nforce
#vlance #vlance
$(X86_ONLY)marvell_yukon $(X86_ONLY)syskonnect $(X86_ONLY)marvell_yukon $(X86_ONLY)syskonnect
$(X86_ONLY)attansic_l2 $(X86_ONLY)ar81xx usb_ecm $(X86_ONLY)attansic_l2 $(X86_ONLY)ar81xx usb_ecm
; ;
#BEOS_ADD_ONS_DRIVERS_ACPI = $(X86_ONLY)acpi_button ; #BEOS_ADD_ONS_DRIVERS_ACPI = $(X86_ONLY)acpi_button ;
@@ -420,7 +420,8 @@ AddSymlinkToHaikuImage beos system add-ons Tracker
AddFilesToHaikuImage beos system add-ons input_server devices AddFilesToHaikuImage beos system add-ons input_server devices
: <input>keyboard <input>mouse <input>wacom ; : <input>keyboard <input>mouse <input>wacom ;
AddFilesToHaikuImage beos system add-ons input_server filters : screen_saver ; AddFilesToHaikuImage beos system add-ons input_server filters : screen_saver ;
AddFilesToHaikuImage beos system add-ons kernel network : stack ; AddFilesToHaikuImage beos system add-ons kernel network
: <net>notifications stack ;
AddFilesToHaikuImage beos system add-ons kernel network devices AddFilesToHaikuImage beos system add-ons kernel network devices
: $(BEOS_NETWORK_DEVICES) ; : $(BEOS_NETWORK_DEVICES) ;
AddFilesToHaikuImage beos system add-ons kernel network datalink_protocols AddFilesToHaikuImage beos system add-ons kernel network datalink_protocols
+7 -8
View File
@@ -24,8 +24,7 @@ struct net_notifications_module_info {
// generic syscall interface // generic syscall interface
#define NET_NOTIFICATIONS_SYSCALLS "network/notifications" #define NET_NOTIFICATIONS_SYSCALLS "network/notifications"
#define NET_NOTIFICATIONS_START_WATCHING 1 #define NET_NOTIFICATIONS_CONTROL_WATCHING 1
#define NET_NOTIFICATIONS_STOP_WATCHING 2
struct net_notifications_control { struct net_notifications_control {
uint32 flags; uint32 flags;
@@ -36,15 +35,15 @@ struct net_notifications_control {
// TODO: the following part of this header should end up in a public header // TODO: the following part of this header should end up in a public header
// some day! // some day!
#define B_NETWORK_INTERFACE_ADDED 1 #define B_NETWORK_INTERFACE_ADDED 0x01
#define B_NETWORK_INTERFACE_REMOVED 2 #define B_NETWORK_INTERFACE_REMOVED 0x02
#define B_NETWORK_INTERFACE_CHANGED 3 #define B_NETWORK_INTERFACE_CHANGED 0x03
#define B_NETWORK_DEVICE_LINK_CHANGED 4 #define B_NETWORK_DEVICE_LINK_CHANGED 0x10
// TODO: add routes, stack unloaded/loaded, ... events // TODO: add routes, stack unloaded/loaded, ... events
enum { enum {
B_WATCH_NETWORK_INTERFACE_CHANGES = 0x0001, B_WATCH_NETWORK_INTERFACE_CHANGES = 0x000f,
B_WATCH_NETWORK_LINK_CHANGES = 0x0002 B_WATCH_NETWORK_LINK_CHANGES = 0x00f0
}; };
#define B_NETWORK_MONITOR '_NTN' #define B_NETWORK_MONITOR '_NTN'
@@ -7,12 +7,18 @@
#include <net_notifications.h> #include <net_notifications.h>
//#include <messaging.h> #include <generic_syscall.h>
#include <Notifications.h> #include <Notifications.h>
#include <util/KMessage.h> #include <util/KMessage.h>
//#define TRACE_NOTIFICATIONS
#ifdef TRACE_NOTIFICATIONS
# define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x)
#else
# define TRACE(x...) ;
#endif
// TODO: add generic syscall interface // TODO: add possibility to remove teams/ports that are gone
static UserMessagingMessageSender sNotificationSender; static UserMessagingMessageSender sNotificationSender;
@@ -75,8 +81,11 @@ static NetNotificationService sNotificationService;
net_listener::~net_listener() net_listener::~net_listener()
{ {
if (dynamic_cast<UserNetListener*>(listener) != NULL) // Only delete the listener if it's one of ours
if (dynamic_cast<UserNetListener*>(listener) != NULL) {
TRACE("delete user listener %p\n", listener);
delete listener; delete listener;
}
} }
@@ -101,21 +110,25 @@ NetNotificationService::~NetNotificationService()
void void
NetNotificationService::Notify(const KMessage& event) NetNotificationService::Notify(const KMessage& event)
{ {
uint32 flags = event.GetInt32("flags", 0); uint32 opcode = event.GetInt32("opcode", 0);
if (flags == 0) if (opcode == 0)
return; return;
TRACE("notify for %lx\n", opcode);
RecursiveLocker _(fRecursiveLock); RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator(); ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) { while (net_listener* listener = iterator.Next()) {
if ((listener->flags & flags) != 0) if ((listener->flags & opcode) != 0) {
TRACE(" notify listener %p for %lx\n", listener, opcode);
listener->listener->EventOccured(*this, &event); listener->listener->EventOccured(*this, &event);
}
} }
iterator = fListeners.GetIterator(); iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) { while (net_listener* listener = iterator.Next()) {
if ((listener->flags & flags) != 0) if ((listener->flags & opcode) != 0)
listener->listener->AllListenersNotified(*this); listener->listener->AllListenersNotified(*this);
} }
} }
@@ -170,8 +183,14 @@ NetNotificationService::RemoveListener(const KMessage* eventSpecifier,
ListenerList::Iterator iterator = fListeners.GetIterator(); ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) { while (net_listener* listener = iterator.Next()) {
if (listener->listener == &notificationListener) { if (listener->listener == &notificationListener) {
TRACE("remove listener %p\n", listener);
iterator.Remove(); iterator.Remove();
delete listener; delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK; return B_OK;
} }
} }
@@ -180,7 +199,7 @@ NetNotificationService::RemoveListener(const KMessage* eventSpecifier,
} }
inline status_t status_t
NetNotificationService::RemoveUserListeners(port_id port, uint32 token) NetNotificationService::RemoveUserListeners(port_id port, uint32 token)
{ {
UserNetListener userListener(port, token); UserNetListener userListener(port, token);
@@ -190,8 +209,14 @@ NetNotificationService::RemoveUserListeners(port_id port, uint32 token)
ListenerList::Iterator iterator = fListeners.GetIterator(); ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) { while (net_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) { if (*listener->listener == userListener) {
TRACE("remove user listener %p\n", listener);
iterator.Remove(); iterator.Remove();
delete listener; delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK; return B_OK;
} }
} }
@@ -237,11 +262,22 @@ NetNotificationService::_AddListener(uint32 flags,
if (listener == NULL) if (listener == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
TRACE("add %slistener %p for %lx\n",
dynamic_cast<UserNetListener*>(&notificationListener) != NULL
? "user " : "", listener, flags);
listener->flags = flags; listener->flags = flags;
listener->listener = &notificationListener; listener->listener = &notificationListener;
RecursiveLocker _(fRecursiveLock); RecursiveLocker _(fRecursiveLock);
if (fListeners.IsEmpty()) {
// The reference counting doesn't work for us, as we'll have to
// ensure our module stays loaded.
module_info* dummy;
get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
}
fListeners.Add(listener); fListeners.Add(listener);
return B_OK; return B_OK;
} }
@@ -250,27 +286,36 @@ NetNotificationService::_AddListener(uint32 flags,
// #pragma mark - User generic syscall // #pragma mark - User generic syscall
status_t static status_t
_user_start_watching_network(uint32 flags, port_id port, uint32 token) net_notifications_control(const char *subsystem, uint32 function, void *buffer,
size_t bufferSize)
{ {
return sNotificationService.UpdateUserListener(flags, port, token); struct net_notifications_control control;
} if (bufferSize != sizeof(struct net_notifications_control)
|| function != NET_NOTIFICATIONS_CONTROL_WATCHING)
return B_BAD_VALUE;
if (user_memcpy(&control, buffer,
sizeof(struct net_notifications_control)) < B_OK)
return B_BAD_ADDRESS;
if (control.flags != 0) {
return sNotificationService.UpdateUserListener(control.flags,
control.port, control.token);
}
status_t return sNotificationService.RemoveUserListeners(control.port,
_user_stop_watching_network(port_id port, uint32 token) control.token);
{
return sNotificationService.RemoveUserListeners(port, token);
} }
// #pragma mark - exported module API // #pragma mark - exported module API
static void static status_t
send_notification(const KMessage* event) send_notification(const KMessage* event)
{ {
sNotificationService.Notify(*event); sNotificationService.Notify(*event);
return B_OK;
} }
@@ -279,10 +324,20 @@ notifications_std_ops(int32 op, ...)
{ {
switch (op) { switch (op) {
case B_MODULE_INIT: case B_MODULE_INIT:
TRACE("init\n");
new(&sNotificationSender) UserMessagingMessageSender(); new(&sNotificationSender) UserMessagingMessageSender();
new(&sNotificationService) NetNotificationService(); new(&sNotificationService) NetNotificationService();
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
net_notifications_control, 1, 0);
return B_OK; return B_OK;
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
TRACE("uninit\n");
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
sNotificationSender.~UserMessagingMessageSender(); sNotificationSender.~UserMessagingMessageSender();
sNotificationService.~NetNotificationService(); sNotificationService.~NetNotificationService();
return B_OK; return B_OK;
@@ -518,7 +518,8 @@ datalink_std_ops(int32 op, ...)
status_t status_t
interface_protocol_init(struct net_interface *_interface, net_datalink_protocol **_protocol) interface_protocol_init(struct net_interface *_interface,
net_datalink_protocol **_protocol)
{ {
net_interface_private *interface = (net_interface_private *)_interface; net_interface_private *interface = (net_interface_private *)_interface;
@@ -547,7 +548,8 @@ interface_protocol_send_data(net_datalink_protocol *_protocol,
net_buffer *buffer) net_buffer *buffer)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol *protocol = (interface_protocol *)_protocol;
net_interface_private *interface = (net_interface_private *)protocol->interface; net_interface_private *interface
= (net_interface_private *)protocol->interface;
// TODO: Need to think about this locking. We can't obtain the // TODO: Need to think about this locking. We can't obtain the
// RX Lock here (nor would it make sense) as the ARP // RX Lock here (nor would it make sense) as the ARP
+4 -1
View File
@@ -186,8 +186,10 @@ add_interface_to_domain(net_domain *_domain,
put_device_interface(deviceInterface); put_device_interface(deviceInterface);
if (status == B_OK) if (status == B_OK) {
list_add_item(&domain->interfaces, interface); list_add_item(&domain->interfaces, interface);
notify_interface_added(interface);
}
return status; return status;
} }
@@ -203,6 +205,7 @@ remove_interface_from_domain(net_interface *interface)
net_domain_private *domain = (net_domain_private *)interface->domain; net_domain_private *domain = (net_domain_private *)interface->domain;
list_remove_item(&domain->interfaces, interface); list_remove_item(&domain->interfaces, interface);
notify_interface_removed(interface);
delete_interface((net_interface_private *)interface); delete_interface((net_interface_private *)interface);
return B_OK; return B_OK;
} }
@@ -764,6 +764,7 @@ unregister_device_monitor(net_device *device, net_device_monitor *monitor)
status_t status_t
device_link_changed(net_device *device) device_link_changed(net_device *device)
{ {
notify_link_changed(device);
return B_OK; return B_OK;
} }
@@ -9,6 +9,7 @@
notification listeners independent from the stack status. notification listeners independent from the stack status.
*/ */
#include <net_device.h>
#include <net_notifications.h> #include <net_notifications.h>
#include <util/KMessage.h> #include <util/KMessage.h>
@@ -20,7 +21,7 @@ static net_notifications_module_info* sNotificationModule;
status_t status_t
notify_interface_added(const char* interface) notify_interface_added(net_interface* interface)
{ {
if (sNotificationModule == NULL) if (sNotificationModule == NULL)
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -29,14 +30,14 @@ notify_interface_added(const char* interface)
KMessage message; KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_ADDED); message.AddInt32("opcode", B_NETWORK_INTERFACE_ADDED);
message.AddString("interface", interface); message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message); return sNotificationModule->send_notification(&message);
} }
status_t status_t
notify_interface_removed(const char* interface) notify_interface_removed(net_interface* interface)
{ {
if (sNotificationModule == NULL) if (sNotificationModule == NULL)
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -45,14 +46,14 @@ notify_interface_removed(const char* interface)
KMessage message; KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_REMOVED); message.AddInt32("opcode", B_NETWORK_INTERFACE_REMOVED);
message.AddString("interface", interface); message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message); return sNotificationModule->send_notification(&message);
} }
status_t status_t
notify_interface_changed(const char* interface) notify_interface_changed(net_interface* interface)
{ {
if (sNotificationModule == NULL) if (sNotificationModule == NULL)
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -61,14 +62,14 @@ notify_interface_changed(const char* interface)
KMessage message; KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_CHANGED); message.AddInt32("opcode", B_NETWORK_INTERFACE_CHANGED);
message.AddString("interface", interface); message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message); return sNotificationModule->send_notification(&message);
} }
status_t status_t
notify_link_changed(const char* interface) notify_link_changed(net_device* device)
{ {
if (sNotificationModule == NULL) if (sNotificationModule == NULL)
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
@@ -77,7 +78,10 @@ notify_link_changed(const char* interface)
KMessage message; KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR); message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_DEVICE_LINK_CHANGED); message.AddInt32("opcode", B_NETWORK_DEVICE_LINK_CHANGED);
message.AddString("interface", interface); message.AddString("device", device->name);
message.AddInt32("media", device->media);
message.AddInt64("link speed", device->link_speed);
message.AddInt32("link quality", device->link_quality);
return sNotificationModule->send_notification(&message); return sNotificationModule->send_notification(&message);
} }
@@ -34,10 +34,10 @@ status_t get_domain_datalink_protocols(net_interface *interface);
status_t put_domain_datalink_protocols(net_interface *interface); status_t put_domain_datalink_protocols(net_interface *interface);
// notifications.cpp // notifications.cpp
status_t notify_interface_added(const char* interface); status_t notify_interface_added(net_interface* interface);
status_t notify_interface_removed(const char* interface); status_t notify_interface_removed(net_interface* interface);
status_t notify_interface_changed(const char* interface); status_t notify_interface_changed(net_interface* interface);
status_t notify_link_changed(const char* interface); status_t notify_link_changed(net_device* device);
status_t init_notifications(); status_t init_notifications();
void uninit_notifications(); void uninit_notifications();
+3 -1
View File
@@ -1,14 +1,16 @@
SubDir HAIKU_TOP src kits network ; SubDir HAIKU_TOP src kits network ;
UsePrivateHeaders libroot net shared ; UsePrivateHeaders app libroot net shared ;
UsePrivateSystemHeaders ; UsePrivateSystemHeaders ;
SharedLibrary libnetwork.so : SharedLibrary libnetwork.so :
init.cpp init.cpp
interfaces.cpp interfaces.cpp
notifications.cpp
socket.cpp socket.cpp
r5_compatibility.cpp r5_compatibility.cpp
: :
be
<libnetwork_dns>dns_dst.o <libnetwork_dns>dns_dst.o
<libnetwork_dns>dns_inet.o <libnetwork_dns>dns_inet.o
<libnetwork_dns>dns_irs.o <libnetwork_dns>dns_irs.o
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
/*! The notifications API uses the generic syscall interface of the
network's stack notification module.
*/
#include <net_notifications.h>
#include <MessengerPrivate.h>
#include <generic_syscall_defs.h>
#include <syscalls.h>
static status_t
check_for_notifications_syscall(void)
{
uint32 version = 0;
return _kern_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, B_SYSCALL_INFO,
&version, sizeof(version));
}
// #pragma mark -
status_t
start_watching_network(uint32 flags, const BMessenger& target)
{
if (check_for_notifications_syscall() != B_OK)
return B_NOT_SUPPORTED;
BMessenger::Private targetPrivate(const_cast<BMessenger&>(target));
net_notifications_control control;
control.flags = flags;
control.port = targetPrivate.Port();
control.token = targetPrivate.Token();
return _kern_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
NET_NOTIFICATIONS_CONTROL_WATCHING, &control,
sizeof(net_notifications_control));
}
status_t
start_watching_network(uint32 flags, const BHandler* handler,
const BLooper* looper)
{
const BMessenger target(handler, looper);
return start_watching_network(flags, target);
}
status_t
stop_watching_network(const BMessenger& target)
{
return start_watching_network(0, target);
// start_watching_network() without flags just stops everything
}
status_t
stop_watching_network(const BHandler* handler, const BLooper* looper)
{
const BMessenger target(handler, looper);
return stop_watching_network(target);
}