Implemented support for default interface and ConnectOnDemand within core. IPCP will probably need more tweaking, did not have a look at that.
Interface statistics are now maintained. If I did not forget anything the core stack is now feature-complete. Only ppp_up must be finished, bugs and hacks found, and modem support added; that's it for R1, I hope. Everyting untested! git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10541 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -110,6 +110,7 @@ pulse_timer(void *data)
|
|||||||
PPPManager::PPPManager()
|
PPPManager::PPPManager()
|
||||||
: fLock("PPPManager"),
|
: fLock("PPPManager"),
|
||||||
fReportLock("PPPManagerReportLock"),
|
fReportLock("PPPManagerReportLock"),
|
||||||
|
fDefaultInterface(NULL),
|
||||||
fReportManager(fReportLock),
|
fReportManager(fReportLock),
|
||||||
fNextID(1)
|
fNextID(1)
|
||||||
{
|
{
|
||||||
@@ -740,6 +741,34 @@ PPPManager::EntryFor(const driver_settings *settings) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PPPManager::SettingsChanged()
|
||||||
|
{
|
||||||
|
// get default interface name and update interfaces if it changed
|
||||||
|
void *handle = load_driver_settings("ptpnet.settings");
|
||||||
|
char *name = get_driver_parameter(handle, "default", NULL, NULL);
|
||||||
|
if(name)
|
||||||
|
name = strdup(name);
|
||||||
|
unload_driver_settings(handle);
|
||||||
|
|
||||||
|
if((!fDefaultInterface && !name) || !strcmp(name, fDefaultInterface))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ppp_interface_entry *entry = EntryFor(fDefaultInterface);
|
||||||
|
if(entry && entry->interface
|
||||||
|
&& entry->interface->StateMachine().Phase() == PPP_DOWN_PHASE)
|
||||||
|
DeleteInterface(entry->interface->ID());
|
||||||
|
|
||||||
|
free(fInterfaceName);
|
||||||
|
fInterfaceName = name;
|
||||||
|
|
||||||
|
ppp_interface_id id = CreateInterfaceWithName(name);
|
||||||
|
entry = EntryFor(id);
|
||||||
|
if(entry && entry->interface)
|
||||||
|
entry->interface->SetConnectOnDemand(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
greater(const void *a, const void *b)
|
greater(const void *a, const void *b)
|
||||||
@@ -827,8 +856,7 @@ PPPManager::_CreateInterface(const char *name, const driver_settings *settings,
|
|||||||
ERROR("KPPPInterface::Up(): Error: could not load ppp_up!\n");
|
ERROR("KPPPInterface::Up(): Error: could not load ppp_up!\n");
|
||||||
resume_thread(app);
|
resume_thread(app);
|
||||||
|
|
||||||
// XXX: What? BeOS' kernel is so &$$§$%! I cannot send anything to the
|
// XXX: Sending to a thread does not work immediately. So, we wait...
|
||||||
// team's main thread before the kernel sent something to it. So, we wait...
|
|
||||||
snooze(150000);
|
snooze(150000);
|
||||||
|
|
||||||
if(send_data(app, 0, &id, sizeof(id)) < B_OK)
|
if(send_data(app, 0, &id, sizeof(id)) < B_OK)
|
||||||
@@ -895,6 +923,9 @@ PPPManager::DeleterThreadEvent()
|
|||||||
{
|
{
|
||||||
LockerHelper locker(fLock);
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
SettingsChanged();
|
||||||
|
// TODO: Use Haiku's kernel node monitoring capabilities
|
||||||
|
|
||||||
// delete and remove marked interfaces
|
// delete and remove marked interfaces
|
||||||
ppp_interface_entry *entry;
|
ppp_interface_entry *entry;
|
||||||
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
@@ -906,6 +937,11 @@ PPPManager::DeleterThreadEvent()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(entry->deleting && entry->accessing <= 0) {
|
if(entry->deleting && entry->accessing <= 0) {
|
||||||
|
// XXX: check twice if it is safe to delete the interface
|
||||||
|
// such that it is reused by _CreateInterface()
|
||||||
|
delete entry->interface;
|
||||||
|
entry->interface = NULL;
|
||||||
|
|
||||||
// only remove entries that do not have ppp_up associated with them
|
// only remove entries that do not have ppp_up associated with them
|
||||||
if(entry->requestThread >= 0) {
|
if(entry->requestThread >= 0) {
|
||||||
thread_info info;
|
thread_info info;
|
||||||
@@ -913,8 +949,17 @@ PPPManager::DeleterThreadEvent()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recreate default interface
|
||||||
|
if(entry->name && fDefaultInterface &&
|
||||||
|
!strcmp(entry->name, fDefaultInterface)) {
|
||||||
|
SettingsChanged();
|
||||||
|
CreateInterfaceWithName(fDefaultInterface);
|
||||||
|
if(entry->interface)
|
||||||
|
entry->interface->SetConnectOnDemand(true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
free(entry->name);
|
free(entry->name);
|
||||||
delete entry->interface;
|
|
||||||
delete entry;
|
delete entry;
|
||||||
fEntries.RemoveItem(index);
|
fEntries.RemoveItem(index);
|
||||||
--index;
|
--index;
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ class PPPManager {
|
|||||||
ppp_interface_entry *EntryFor(const char *name, int32 *saveIndex = NULL) const;
|
ppp_interface_entry *EntryFor(const char *name, int32 *saveIndex = NULL) const;
|
||||||
ppp_interface_entry *EntryFor(const driver_settings *settings) const;
|
ppp_interface_entry *EntryFor(const driver_settings *settings) const;
|
||||||
|
|
||||||
|
void SettingsChanged();
|
||||||
|
|
||||||
ppp_interface_id NextID()
|
ppp_interface_id NextID()
|
||||||
{ return (ppp_interface_id) atomic_add((int32*) &fNextID, 1); }
|
{ return (ppp_interface_id) atomic_add((int32*) &fNextID, 1); }
|
||||||
|
|
||||||
@@ -74,6 +76,7 @@ class PPPManager {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock, fReportLock;
|
BLocker fLock, fReportLock;
|
||||||
|
char *fDefaultInterface;
|
||||||
KPPPReportManager fReportManager;
|
KPPPReportManager fReportManager;
|
||||||
TemplateList<ppp_interface_entry*> fEntries;
|
TemplateList<ppp_interface_entry*> fEntries;
|
||||||
ppp_interface_id fNextID;
|
ppp_interface_id fNextID;
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry,
|
|||||||
fConnectRetry(0),
|
fConnectRetry(0),
|
||||||
fConnectRetriesLimit(0),
|
fConnectRetriesLimit(0),
|
||||||
fManager(NULL),
|
fManager(NULL),
|
||||||
|
fConnectedSince(0),
|
||||||
fIdleSince(0),
|
fIdleSince(0),
|
||||||
fMRU(1500),
|
fMRU(1500),
|
||||||
fInterfaceMTU(1498),
|
fInterfaceMTU(1498),
|
||||||
@@ -121,8 +122,8 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry,
|
|||||||
if(name) {
|
if(name) {
|
||||||
// load settings from description file
|
// load settings from description file
|
||||||
char path[B_PATH_NAME_LENGTH];
|
char path[B_PATH_NAME_LENGTH];
|
||||||
sprintf(path, "pppidf/%s", name);
|
sprintf(path, "ptpnet/%s", name);
|
||||||
// XXX: TODO: change base path to "/etc/ppp" when settings API supports it
|
// XXX: TODO: change base path to "/etc/ptpnet"
|
||||||
|
|
||||||
void *handle = load_driver_settings(path);
|
void *handle = load_driver_settings(path);
|
||||||
if(!handle) {
|
if(!handle) {
|
||||||
@@ -489,6 +490,13 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
|
|||||||
UpdateProfile();
|
UpdateProfile();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PPPC_GET_STATISTICS: {
|
||||||
|
if(length < sizeof(ppp_statistics) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
memcpy(data, &fStatistics, sizeof(ppp_statistics));
|
||||||
|
} break;
|
||||||
|
|
||||||
case PPPC_CONTROL_DEVICE: {
|
case PPPC_CONTROL_DEVICE: {
|
||||||
if(length < sizeof(ppp_control_info) || !data)
|
if(length < sizeof(ppp_control_info) || !data)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1373,12 +1381,22 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
|
|||||||
// pass to device/children
|
// pass to device/children
|
||||||
if(!IsMultilink() || Parent()) {
|
if(!IsMultilink() || Parent()) {
|
||||||
// check if packet is too big for device
|
// check if packet is too big for device
|
||||||
if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > MRU())
|
uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len :
|
||||||
|| packet->m_len > MRU()) {
|
packet->m_len;
|
||||||
|
|
||||||
|
if(length > MRU()) {
|
||||||
m_freem(packet);
|
m_freem(packet);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: always use atomic_add64 when Haiku is finished
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
atomic_add64(&fStatistics.bytesSent, length);
|
||||||
|
atomic_add64(&fStatistics.packetsSent, 1);
|
||||||
|
#else
|
||||||
|
atomic_add((int32*) &fStatistics.bytesSent, length);
|
||||||
|
atomic_add((int32*) &fStatistics.packetsSent, 1);
|
||||||
|
#endif
|
||||||
return SendToNext(packet, 0);
|
return SendToNext(packet, 0);
|
||||||
// this is normally the device, but there can be something inbetween
|
// this is normally the device, but there can be something inbetween
|
||||||
} else {
|
} else {
|
||||||
@@ -1488,6 +1506,9 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len :
|
||||||
|
packet->m_len;
|
||||||
|
|
||||||
// decode ppp frame and recognize PFC
|
// decode ppp frame and recognize PFC
|
||||||
uint16 protocolNumber = *mtod(packet, uint8*);
|
uint16 protocolNumber = *mtod(packet, uint8*);
|
||||||
if(protocolNumber & 1) {
|
if(protocolNumber & 1) {
|
||||||
@@ -1497,6 +1518,14 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet)
|
|||||||
m_adj(packet, 2);
|
m_adj(packet, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: always use atomic_add64 when Haiku is finished
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
atomic_add64(&fStatistics.bytesReceived, length);
|
||||||
|
atomic_add64(&fStatistics.packetsReceived, 1);
|
||||||
|
#else
|
||||||
|
atomic_add((int32*) &fStatistics.bytesReceived, length);
|
||||||
|
atomic_add((int32*) &fStatistics.packetsReceived, 1);
|
||||||
|
#endif
|
||||||
return Receive(packet, protocolNumber);
|
return Receive(packet, protocolNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ KPPPProfile::LoadSettings(const driver_settings *profile,
|
|||||||
name = Interface().Name();
|
name = Interface().Name();
|
||||||
|
|
||||||
if(name) {
|
if(name) {
|
||||||
sprintf(path, "pppidf/profile/%s", name);
|
sprintf(path, "ptpnet/profile/%s", name);
|
||||||
void *handle = load_driver_settings(path);
|
void *handle = load_driver_settings(path);
|
||||||
if(handle) {
|
if(handle) {
|
||||||
fSettings = dup_driver_settings(get_driver_settings(handle));
|
fSettings = dup_driver_settings(get_driver_settings(handle));
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ KPPPStateMachine::NewPhase(ppp_phase next)
|
|||||||
|
|
||||||
Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_SUCCESSFUL,
|
Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_SUCCESSFUL,
|
||||||
&fInterface.fID, sizeof(ppp_interface_id));
|
&fInterface.fID, sizeof(ppp_interface_id));
|
||||||
|
Interface().fConnectedSince = system_time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
#include <KPPPDefs.h>
|
#include <KPPPDefs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _PPP_CONTROL__H
|
||||||
|
#include <PPPControl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _K_PPP_LCP__H
|
#ifndef _K_PPP_LCP__H
|
||||||
#include <KPPPLCP.h>
|
#include <KPPPLCP.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -262,6 +266,8 @@ class KPPPInterface : public KPPPLayer {
|
|||||||
|
|
||||||
ppp_interface_module_info *fManager;
|
ppp_interface_module_info *fManager;
|
||||||
|
|
||||||
|
ppp_statistics fStatistics;
|
||||||
|
bigtime_t fConnectedSince;
|
||||||
uint32 fIdleSince, fDisconnectAfterIdleSince;
|
uint32 fIdleSince, fDisconnectAfterIdleSince;
|
||||||
bool fUpdateIdleSince;
|
bool fUpdateIdleSince;
|
||||||
uint32 fMRU, fInterfaceMTU, fHeaderLength;
|
uint32 fMRU, fInterfaceMTU, fHeaderLength;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ enum ppp_control_ops {
|
|||||||
PPPC_SET_AUTO_RECONNECT,
|
PPPC_SET_AUTO_RECONNECT,
|
||||||
PPPC_HAS_INTERFACE_SETTINGS,
|
PPPC_HAS_INTERFACE_SETTINGS,
|
||||||
PPPC_SET_PROFILE,
|
PPPC_SET_PROFILE,
|
||||||
|
PPPC_GET_STATISTICS,
|
||||||
|
|
||||||
// handler access
|
// handler access
|
||||||
PPPC_CONTROL_DEVICE = PPP_INTERFACE_OPS_START + 0xFF,
|
PPPC_CONTROL_DEVICE = PPP_INTERFACE_OPS_START + 0xFF,
|
||||||
@@ -153,6 +154,8 @@ typedef struct ppp_interface_info {
|
|||||||
|
|
||||||
uint32 connectRetry, connectRetriesLimit;
|
uint32 connectRetry, connectRetriesLimit;
|
||||||
uint32 connectRetryDelay, reconnectDelay;
|
uint32 connectRetryDelay, reconnectDelay;
|
||||||
|
bigtime_t connectedSince;
|
||||||
|
// undefined if disconnected
|
||||||
uint32 idleSince, disconnectAfterIdleSince;
|
uint32 idleSince, disconnectAfterIdleSince;
|
||||||
|
|
||||||
bool doesConnectOnDemand, doesAutoReconnect, hasDevice, isMultilink, hasParent;
|
bool doesConnectOnDemand, doesAutoReconnect, hasDevice, isMultilink, hasParent;
|
||||||
@@ -167,6 +170,18 @@ typedef struct ppp_interface_info_t {
|
|||||||
} ppp_interface_info_t;
|
} ppp_interface_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
//! Structure used by \c PPPC_GET_STATISTICS.
|
||||||
|
typedef struct ppp_statistics {
|
||||||
|
uint64 bytesReceived, packetsReceived;
|
||||||
|
uint64 bytesSent, packetsSent;
|
||||||
|
|
||||||
|
// TODO: currently unused
|
||||||
|
uint64 errorBytesReceived, errorPacketsReceived;
|
||||||
|
|
||||||
|
// TODO: add compression statistics?
|
||||||
|
uint8 _reserved_[80];
|
||||||
|
} ppp_statistics;
|
||||||
|
|
||||||
//! Structure used by \c PPPC_GET_DEVICE_INFO.
|
//! Structure used by \c PPPC_GET_DEVICE_INFO.
|
||||||
typedef struct ppp_device_info {
|
typedef struct ppp_device_info {
|
||||||
char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
|
char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ typedef uint32 ppp_interface_id;
|
|||||||
|
|
||||||
|
|
||||||
// settings keys
|
// settings keys
|
||||||
#define PPP_ASK_BEFORE_CONNECTING_KEY "AskBeforeConnecting"
|
#define PPP_ASK_BEFORE_CONNECTING_KEY "AskBeforeConnecting"
|
||||||
// userland ppp_up and preflet handle this key
|
// userland ppp_up and preflet handle this key
|
||||||
#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
|
#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
|
||||||
#define PPP_MODE_KEY "Mode"
|
#define PPP_MODE_KEY "Mode"
|
||||||
#define PPP_CONNECT_RETRIES_LIMIT_KEY "ConnectRetriesLimit"
|
#define PPP_CONNECT_RETRIES_LIMIT_KEY "ConnectRetriesLimit"
|
||||||
#define PPP_CONNECT_RETRY_DELAY_KEY "ConnectRetryDelay"
|
#define PPP_CONNECT_RETRY_DELAY_KEY "ConnectRetryDelay"
|
||||||
#define PPP_AUTO_RECONNECT_KEY "AutoReconnect"
|
#define PPP_AUTO_RECONNECT_KEY "AutoReconnect"
|
||||||
#define PPP_RECONNECT_DELAY_KEY "ReconnectDelay"
|
#define PPP_RECONNECT_DELAY_KEY "ReconnectDelay"
|
||||||
#define PPP_LOAD_MODULE_KEY "LoadModule"
|
#define PPP_LOAD_MODULE_KEY "LoadModule"
|
||||||
#define PPP_PROTOCOL_KEY "Protocol"
|
#define PPP_PROTOCOL_KEY "Protocol"
|
||||||
@@ -35,8 +35,12 @@ typedef uint32 ppp_interface_id;
|
|||||||
|
|
||||||
// path defines
|
// path defines
|
||||||
#define PPP_MODULES_PATH NETWORK_MODULES_ROOT "ppp"
|
#define PPP_MODULES_PATH NETWORK_MODULES_ROOT "ppp"
|
||||||
#define PPP_INTERFACE_SETTINGS_PATH "/boot/home/config/settings/kernel/drivers/pppidf"
|
#define PTP_INTERFACE_SETTINGS_PATH \
|
||||||
// should be: /etc/ppp
|
"/boot/home/config/settings/kernel/drivers/ptpnet"
|
||||||
|
// should be: /etc/ptpnet
|
||||||
|
#define PTP_SETTINGS_PATH \
|
||||||
|
"/boot/home/config/settings/kernel/drivers/ptpnet.settings"
|
||||||
|
// should be: /etc/ptpnet.settings
|
||||||
|
|
||||||
// built-in protocols
|
// built-in protocols
|
||||||
#define PPP_LCP_PROTOCOL 0xC021
|
#define PPP_LCP_PROTOCOL 0xC021
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ PPPInterface::GetSettingsEntry(BEntry *entry) const
|
|||||||
else if(!entry || strlen(Name()) == 0)
|
else if(!entry || strlen(Name()) == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
BDirectory directory(PPP_INTERFACE_SETTINGS_PATH);
|
BDirectory directory(PTP_INTERFACE_SETTINGS_PATH);
|
||||||
return directory.FindEntry(Name(), entry, true);
|
return directory.FindEntry(Name(), entry, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ PPPManager::CreateInterface(const driver_settings *settings,
|
|||||||
/*! \brief Creates an interface with the given name and profile.
|
/*! \brief Creates an interface with the given name and profile.
|
||||||
|
|
||||||
If the interface already exists its ID will be returned.
|
If the interface already exists its ID will be returned.
|
||||||
Every PPP interface has a profile. By default it checks if the pppidf/profile
|
Every PPP interface has a profile. By default it checks if the ptpnet/profile
|
||||||
folder contains a profile with the interface's name. Otherwise the interface's
|
folder contains a profile with the interface's name. Otherwise the interface's
|
||||||
settings become its profile. This has the advantage that you can put the profile
|
settings become its profile. This has the advantage that you can put the profile
|
||||||
and the settings into the same file which simplifies your PPP configuration if
|
and the settings into the same file which simplifies your PPP configuration if
|
||||||
|
|||||||
Reference in New Issue
Block a user