From e91b73741246bd6859046aac533269726d8c485a Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Mon, 27 Dec 2004 15:02:14 +0000 Subject: [PATCH] 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 --- .../network/interfaces/ppp/PPPManager.cpp | 51 +++++++++++++++++-- .../network/interfaces/ppp/PPPManager.h | 3 ++ .../ppp/shared/libkernelppp/KPPPInterface.cpp | 37 ++++++++++++-- .../ppp/shared/libkernelppp/KPPPProfile.cpp | 2 +- .../shared/libkernelppp/KPPPStateMachine.cpp | 1 + .../libkernelppp/headers/KPPPInterface.h | 6 +++ .../shared/libkernelppp/headers/PPPControl.h | 15 ++++++ .../ppp/shared/libkernelppp/headers/PPPDefs.h | 14 +++-- .../ppp/shared/libppp/PPPInterface.cpp | 2 +- .../network/ppp/shared/libppp/PPPManager.cpp | 2 +- 10 files changed, 118 insertions(+), 15 deletions(-) diff --git a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp index bcda86d872..e38c87068f 100644 --- a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp @@ -110,6 +110,7 @@ pulse_timer(void *data) PPPManager::PPPManager() : fLock("PPPManager"), fReportLock("PPPManagerReportLock"), + fDefaultInterface(NULL), fReportManager(fReportLock), 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 int 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"); resume_thread(app); - // XXX: What? BeOS' kernel is so &$$ยง$%! I cannot send anything to the - // team's main thread before the kernel sent something to it. So, we wait... + // XXX: Sending to a thread does not work immediately. So, we wait... snooze(150000); if(send_data(app, 0, &id, sizeof(id)) < B_OK) @@ -895,6 +923,9 @@ PPPManager::DeleterThreadEvent() { LockerHelper locker(fLock); + SettingsChanged(); + // TODO: Use Haiku's kernel node monitoring capabilities + // delete and remove marked interfaces ppp_interface_entry *entry; for(int32 index = 0; index < fEntries.CountItems(); index++) { @@ -906,6 +937,11 @@ PPPManager::DeleterThreadEvent() } 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 if(entry->requestThread >= 0) { thread_info info; @@ -913,8 +949,17 @@ PPPManager::DeleterThreadEvent() 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); - delete entry->interface; delete entry; fEntries.RemoveItem(index); --index; diff --git a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.h b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.h index 5874192697..c31747f377 100644 --- a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.h +++ b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.h @@ -60,6 +60,8 @@ class PPPManager { ppp_interface_entry *EntryFor(const char *name, int32 *saveIndex = NULL) const; ppp_interface_entry *EntryFor(const driver_settings *settings) const; + void SettingsChanged(); + ppp_interface_id NextID() { return (ppp_interface_id) atomic_add((int32*) &fNextID, 1); } @@ -74,6 +76,7 @@ class PPPManager { private: BLocker fLock, fReportLock; + char *fDefaultInterface; KPPPReportManager fReportManager; TemplateList fEntries; ppp_interface_id fNextID; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp index 47c918b953..c2e7b3cecf 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp @@ -95,6 +95,7 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, fConnectRetry(0), fConnectRetriesLimit(0), fManager(NULL), + fConnectedSince(0), fIdleSince(0), fMRU(1500), fInterfaceMTU(1498), @@ -121,8 +122,8 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, if(name) { // load settings from description file char path[B_PATH_NAME_LENGTH]; - sprintf(path, "pppidf/%s", name); - // XXX: TODO: change base path to "/etc/ppp" when settings API supports it + sprintf(path, "ptpnet/%s", name); + // XXX: TODO: change base path to "/etc/ptpnet" void *handle = load_driver_settings(path); if(!handle) { @@ -489,6 +490,13 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) UpdateProfile(); } 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: { if(length < sizeof(ppp_control_info) || !data) return B_ERROR; @@ -1373,12 +1381,22 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber) // pass to device/children if(!IsMultilink() || Parent()) { // check if packet is too big for device - if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > MRU()) - || packet->m_len > MRU()) { + uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len : + packet->m_len; + + if(length > MRU()) { m_freem(packet); 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); // this is normally the device, but there can be something inbetween } else { @@ -1488,6 +1506,9 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet) return B_ERROR; } + uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len : + packet->m_len; + // decode ppp frame and recognize PFC uint16 protocolNumber = *mtod(packet, uint8*); if(protocolNumber & 1) { @@ -1497,6 +1518,14 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet) 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); } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp index e20b4af8eb..01821befc4 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp @@ -82,7 +82,7 @@ KPPPProfile::LoadSettings(const driver_settings *profile, name = Interface().Name(); if(name) { - sprintf(path, "pppidf/profile/%s", name); + sprintf(path, "ptpnet/profile/%s", name); void *handle = load_driver_settings(path); if(handle) { fSettings = dup_driver_settings(get_driver_settings(handle)); diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp index a91cd028df..f677727008 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp @@ -129,6 +129,7 @@ KPPPStateMachine::NewPhase(ppp_phase next) Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_SUCCESSFUL, &fInterface.fID, sizeof(ppp_interface_id)); + Interface().fConnectedSince = system_time(); } } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h index 2199001031..ee02cbec00 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h @@ -12,6 +12,10 @@ #include #endif +#ifndef _PPP_CONTROL__H +#include +#endif + #ifndef _K_PPP_LCP__H #include #endif @@ -262,6 +266,8 @@ class KPPPInterface : public KPPPLayer { ppp_interface_module_info *fManager; + ppp_statistics fStatistics; + bigtime_t fConnectedSince; uint32 fIdleSince, fDisconnectAfterIdleSince; bool fUpdateIdleSince; uint32 fMRU, fInterfaceMTU, fHeaderLength; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h index ee7e7d15a0..b4985824bc 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h @@ -51,6 +51,7 @@ enum ppp_control_ops { PPPC_SET_AUTO_RECONNECT, PPPC_HAS_INTERFACE_SETTINGS, PPPC_SET_PROFILE, + PPPC_GET_STATISTICS, // handler access PPPC_CONTROL_DEVICE = PPP_INTERFACE_OPS_START + 0xFF, @@ -153,6 +154,8 @@ typedef struct ppp_interface_info { uint32 connectRetry, connectRetriesLimit; uint32 connectRetryDelay, reconnectDelay; + bigtime_t connectedSince; + // undefined if disconnected uint32 idleSince, disconnectAfterIdleSince; bool doesConnectOnDemand, doesAutoReconnect, hasDevice, isMultilink, hasParent; @@ -167,6 +170,18 @@ typedef struct 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. typedef struct ppp_device_info { char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h index 45e3a1df43..eb674c06b3 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h @@ -15,13 +15,13 @@ typedef uint32 ppp_interface_id; // settings keys -#define PPP_ASK_BEFORE_CONNECTING_KEY "AskBeforeConnecting" +#define PPP_ASK_BEFORE_CONNECTING_KEY "AskBeforeConnecting" // userland ppp_up and preflet handle this key #define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince" #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_AUTO_RECONNECT_KEY "AutoReconnect" +#define PPP_AUTO_RECONNECT_KEY "AutoReconnect" #define PPP_RECONNECT_DELAY_KEY "ReconnectDelay" #define PPP_LOAD_MODULE_KEY "LoadModule" #define PPP_PROTOCOL_KEY "Protocol" @@ -35,8 +35,12 @@ typedef uint32 ppp_interface_id; // path defines #define PPP_MODULES_PATH NETWORK_MODULES_ROOT "ppp" -#define PPP_INTERFACE_SETTINGS_PATH "/boot/home/config/settings/kernel/drivers/pppidf" - // should be: /etc/ppp +#define PTP_INTERFACE_SETTINGS_PATH \ + "/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 #define PPP_LCP_PROTOCOL 0xC021 diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp index e2733c885b..d9ac67ba63 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp @@ -158,7 +158,7 @@ PPPInterface::GetSettingsEntry(BEntry *entry) const else if(!entry || strlen(Name()) == 0) return B_BAD_VALUE; - BDirectory directory(PPP_INTERFACE_SETTINGS_PATH); + BDirectory directory(PTP_INTERFACE_SETTINGS_PATH); return directory.FindEntry(Name(), entry, true); } diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp index 6f1610fb28..f616004d9f 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp @@ -133,7 +133,7 @@ PPPManager::CreateInterface(const driver_settings *settings, /*! \brief Creates an interface with the given name and profile. 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 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