mirror of git://git.sysmocom.de/ofono
GAtPPP: Add PFC option support
This commit is contained in:
parent
84ccc874da
commit
fed838f79f
|
@ -84,6 +84,7 @@ struct _GAtPPP {
|
|||
guint guard_timeout_source;
|
||||
gboolean suspended;
|
||||
gboolean xmit_acfc;
|
||||
gboolean xmit_pfc;
|
||||
};
|
||||
|
||||
void ppp_debug(GAtPPP *ppp, const char *str)
|
||||
|
@ -172,6 +173,7 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
|
|||
struct ppp_header *header = (struct ppp_header *) buf;
|
||||
gboolean acfc_frame = (header->address != PPP_ADDR_FIELD
|
||||
|| header->control != PPP_CTRL);
|
||||
gboolean pfc_frame = FALSE;
|
||||
guint16 protocol;
|
||||
const guint8 *packet;
|
||||
|
||||
|
@ -183,6 +185,20 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
|
|||
packet = ppp_info(buf);
|
||||
}
|
||||
|
||||
pfc_frame = (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
|
||||
protocol != IPCP_PROTO && protocol != PPP_IP_PROTO);
|
||||
|
||||
if (pfc_frame) {
|
||||
guint8 proto = (protocol >> 8) & 0xFF ;
|
||||
packet = packet - 1;
|
||||
/*
|
||||
* The only protocol that can be compressed is PPP_IP_PROTO
|
||||
* because first byte is 0x00.
|
||||
*/
|
||||
if (proto == PPP_IP_COMPRESSED_PROTO)
|
||||
protocol = PPP_IP_PROTO;
|
||||
}
|
||||
|
||||
if (ppp_drop_packet(ppp, protocol))
|
||||
return;
|
||||
|
||||
|
@ -264,6 +280,32 @@ static void ppp_send_acfc_frame(GAtPPP *ppp, guint8 *packet,
|
|||
if (ppp->xmit_acfc)
|
||||
offset = 2;
|
||||
|
||||
/* We remove the only address and control field */
|
||||
if (g_at_hdlc_send(ppp->hdlc, packet + offset,
|
||||
infolen + sizeof(*header) - offset)
|
||||
== FALSE)
|
||||
DBG(ppp, "Failed to send a frame\n");
|
||||
}
|
||||
|
||||
static void ppp_send_acfc_pfc_frame(GAtPPP *ppp, guint8 *packet,
|
||||
guint infolen)
|
||||
{
|
||||
struct ppp_header *header = (struct ppp_header *) packet;
|
||||
guint offset = 0;
|
||||
|
||||
if (ppp->xmit_acfc && ppp->xmit_pfc)
|
||||
offset = 3;
|
||||
else if (ppp->xmit_acfc)
|
||||
offset = 2;
|
||||
else if (ppp->xmit_pfc) {
|
||||
/*
|
||||
* We remove only the 1st byte that is 0x00 of protocol field.
|
||||
*/
|
||||
packet[2] = packet[1];
|
||||
packet[1] = packet[0];
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
if (g_at_hdlc_send(ppp->hdlc, packet + offset,
|
||||
infolen + sizeof(*header) - offset)
|
||||
== FALSE)
|
||||
|
@ -285,9 +327,18 @@ void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
|
|||
break;
|
||||
case CHAP_PROTOCOL:
|
||||
case IPCP_PROTO:
|
||||
case PPP_IP_PROTO:
|
||||
/*
|
||||
* We can't use PFC option because first byte of CHAP_PROTOCOL
|
||||
* and IPCP_PROTO is not equal to 0x00
|
||||
*/
|
||||
ppp_send_acfc_frame(ppp, packet, infolen);
|
||||
break;
|
||||
case PPP_IP_PROTO:
|
||||
/*
|
||||
* We can't use both compression options if they are negotiated
|
||||
*/
|
||||
ppp_send_acfc_pfc_frame(ppp, packet, infolen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,6 +486,11 @@ void ppp_set_xmit_acfc(GAtPPP *ppp, gboolean acfc)
|
|||
ppp->xmit_acfc = acfc;
|
||||
}
|
||||
|
||||
void ppp_set_xmit_pfc(GAtPPP *ppp, gboolean pfc)
|
||||
{
|
||||
ppp->xmit_pfc = pfc;
|
||||
}
|
||||
|
||||
static void io_disconnect(gpointer user_data)
|
||||
{
|
||||
GAtPPP *ppp = user_data;
|
||||
|
@ -708,6 +764,11 @@ void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled)
|
|||
lcp_set_acfc_enabled(ppp->lcp, enabled);
|
||||
}
|
||||
|
||||
void g_at_ppp_set_pfc_enabled(GAtPPP *ppp, gboolean enabled)
|
||||
{
|
||||
lcp_set_pfc_enabled(ppp->lcp, enabled);
|
||||
}
|
||||
|
||||
static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip)
|
||||
{
|
||||
GAtPPP *ppp;
|
||||
|
|
|
@ -80,6 +80,7 @@ void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip,
|
|||
const char *dns1, const char *dns2);
|
||||
|
||||
void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled);
|
||||
void g_at_ppp_set_pfc_enabled(GAtPPP *ppp, gboolean enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define PPP_IP_PROTO 0x0021
|
||||
#define MD5 5
|
||||
|
||||
#define PPP_IP_COMPRESSED_PROTO 0x21
|
||||
|
||||
#define DBG(p, fmt, arg...) do { \
|
||||
char *str = g_strdup_printf("%s:%s() " fmt, __FILE__, \
|
||||
__FUNCTION__ , ## arg); \
|
||||
|
@ -96,6 +98,7 @@ struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean dormant);
|
|||
void lcp_free(struct pppcp_data *lcp);
|
||||
void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len);
|
||||
void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled);
|
||||
void lcp_set_pfc_enabled(struct pppcp_data *pppcp, gboolean enabled);
|
||||
|
||||
/* IPCP related functions */
|
||||
struct pppcp_data *ipcp_new(GAtPPP *ppp, gboolean is_server, guint32 ip);
|
||||
|
@ -133,4 +136,5 @@ void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm);
|
|||
void ppp_set_xmit_accm(GAtPPP *ppp, guint32 accm);
|
||||
void ppp_set_mtu(GAtPPP *ppp, const guint8 *data);
|
||||
void ppp_set_xmit_acfc(GAtPPP *ppp, gboolean acfc);
|
||||
void ppp_set_xmit_pfc(GAtPPP *ppp, gboolean pfc);
|
||||
struct ppp_header *ppp_packet_new(gsize infolen, guint16 protocol);
|
||||
|
|
|
@ -58,12 +58,13 @@ enum lcp_options {
|
|||
ACFC = 8,
|
||||
};
|
||||
|
||||
/* Maximum size of all options, we only ever request ACCM, MRU and ACFC */
|
||||
#define MAX_CONFIG_OPTION_SIZE 12
|
||||
/* Maximum size of all options, we only ever request ACCM, MRU, ACFC and PFC */
|
||||
#define MAX_CONFIG_OPTION_SIZE 14
|
||||
|
||||
#define REQ_OPTION_ACCM 0x1
|
||||
#define REQ_OPTION_MRU 0x2
|
||||
#define REQ_OPTION_ACFC 0x4
|
||||
#define REQ_OPTION_PFC 0x8
|
||||
|
||||
struct lcp_data {
|
||||
guint8 options[MAX_CONFIG_OPTION_SIZE];
|
||||
|
@ -108,6 +109,13 @@ static void lcp_generate_config_options(struct lcp_data *lcp)
|
|||
len += 2;
|
||||
}
|
||||
|
||||
if (lcp->req_options & REQ_OPTION_PFC) {
|
||||
lcp->options[len] = PFC;
|
||||
lcp->options[len + 1] = 2;
|
||||
|
||||
len += 2;
|
||||
}
|
||||
|
||||
lcp->options_len = len;
|
||||
}
|
||||
|
||||
|
@ -293,9 +301,17 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
|
|||
ppp_set_mtu(ppp, ppp_option_iter_get_data(&iter));
|
||||
break;
|
||||
case MAGIC_NUMBER:
|
||||
case PFC:
|
||||
/* don't care */
|
||||
break;
|
||||
case PFC:
|
||||
{
|
||||
struct lcp_data *lcp = pppcp_get_data(pppcp);
|
||||
|
||||
if (lcp->req_options & REQ_OPTION_PFC)
|
||||
ppp_set_xmit_pfc(ppp, TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
case ACFC:
|
||||
{
|
||||
struct lcp_data *lcp = pppcp_get_data(pppcp);
|
||||
|
@ -367,3 +383,16 @@ void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled)
|
|||
lcp_generate_config_options(lcp);
|
||||
pppcp_set_local_options(pppcp, lcp->options, lcp->options_len);
|
||||
}
|
||||
|
||||
void lcp_set_pfc_enabled(struct pppcp_data *pppcp, gboolean enabled)
|
||||
{
|
||||
struct lcp_data *lcp = pppcp_get_data(pppcp);
|
||||
|
||||
if (enabled == TRUE)
|
||||
lcp->req_options |= REQ_OPTION_PFC;
|
||||
else
|
||||
lcp->req_options &= ~REQ_OPTION_PFC;
|
||||
|
||||
lcp_generate_config_options(lcp);
|
||||
pppcp_set_local_options(pppcp, lcp->options, lcp->options_len);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue