Commit 851785c4 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Convert ISDN/PPP to inl_priv / ind_priv

Interface type specific stuff is now gone from isdn_net_lib and
taken care of in the individual interface type modules.
parent d26d04dc
......@@ -83,20 +83,15 @@ struct isdn_net_phone {
char num[ISDN_MSNLEN];
};
/*
Principles when extending structures for generic encapsulation protocol
("concap") support:
- Stuff which is hardware specific (here i4l-specific) goes in
the netdev -> local structure (here: isdn_net_local)
- Stuff which is encapsulation protocol specific goes in the structure
which holds the linux device structure (here: isdn_net_device)
*/
/* per network interface data (dev->priv) */
struct isdn_net_local_s {
ulong magic;
struct net_device dev; /* interface to upper levels */
struct net_device_stats stats; /* Ethernet Statistics */
struct isdn_netif_ops *ops;
void *inl_priv; /* interface types can put their
private data here */
int flags; /* Connection-flags */
int dialmax; /* Max. Number of Dial-retries */
int dialtimeout; /* How long shall we try on dialing */
......@@ -134,25 +129,6 @@ struct isdn_net_local_s {
struct list_head running_devs; /* member of global running_devs */
atomic_t refcnt; /* references held by ISDN code */
#ifdef CONFIG_ISDN_PPP
unsigned int mp_cfg;
u32 mp_txseq;
struct sk_buff_head mp_frags; /* fragments sl list */
u32 mp_rxseq; /* last processed packet seq #: any
packets with smaller seq # will
be dropped unconditionally */
struct ippp_ccp *ccp;
unsigned long debug;
#ifdef CONFIG_ISDN_PPP_VJ
unsigned char *cbuf;
struct slcompress *slcomp;
#endif
#endif
void *inl_priv; /* interface types can put their
private data here */
struct isdn_netif_ops *ops;
struct net_device dev; /* interface to upper levels */
};
......@@ -184,7 +160,6 @@ struct isdn_net_dev_s {
int chargeint; /* Interval between charge-infos */
int pppbind; /* ippp device for bindings */
struct ipppd *ipppd; /* /dev/ipppX which controls us */
struct sk_buff_head super_tx_queue; /* List of supervisory frames to */
/* be transmitted asap */
......@@ -199,12 +174,6 @@ struct isdn_net_dev_s {
char name[10]; /* Name of device */
struct list_head global_list; /* global list of all isdn_net_devs */
#ifdef CONFIG_ISDN_PPP
unsigned int pppcfg;
u32 mp_rxseq; /* last seq no seen on this channel */
struct ippp_ccp *ccp;
unsigned long debug;
#endif
void *ind_priv; /* interface types can put their
private data here */
};
......
......@@ -212,6 +212,8 @@ static ssize_t
ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
{
isdn_net_dev *idev;
struct inl_ppp *inl_ppp;
struct ind_ppp *ind_ppp;
struct ipppd *ipppd;
struct sk_buff *skb;
char *p;
......@@ -235,6 +237,8 @@ ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
retval = -ENODEV;
goto out;
}
ind_ppp = idev->ind_priv;
inl_ppp = idev->mlp->inl_priv;
/* Daemon needs to send at least full header, AC + proto */
if (count < 4) {
retval = -EMSGSIZE;
......@@ -259,10 +263,10 @@ ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
/* Keeps CCP/compression states in sync */
switch (proto) {
case PPP_CCP:
ippp_ccp_send_ccp(idev->mlp->ccp, skb);
ippp_ccp_send_ccp(inl_ppp->ccp, skb);
break;
case PPP_CCPFRAG:
ippp_ccp_send_ccp(idev->ccp, skb);
ippp_ccp_send_ccp(ind_ppp->ccp, skb);
break;
}
/* FIXME: Somewhere we need protection against the
......@@ -334,6 +338,8 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
unsigned long arg)
{
isdn_net_dev *idev;
struct ind_ppp *ind_ppp = NULL;
struct inl_ppp *inl_ppp = NULL;
unsigned long val;
int r;
struct ipppd *is;
......@@ -346,7 +352,10 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
// FIXME that needs locking?
idev = is->idev;
if (idev) {
ind_ppp = idev->ind_priv;
inl_ppp = idev->mlp->inl_priv;
}
switch (cmd) {
case PPPIOCGUNIT: /* get ppp/isdn unit number */
r = set_arg(arg, &is->unit, sizeof(is->unit));
......@@ -360,8 +369,8 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
break;
is->debug = val;
if (idev) {
idev->debug = val;
idev->mlp->debug = val;
ind_ppp->debug = val;
inl_ppp->debug = val;
}
break;
case PPPIOCGCOMPRESSORS:
......@@ -396,29 +405,29 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
r = set_arg(arg, idev->name, strlen(idev->name)+1);
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
r = set_arg(arg, &idev->mlp->mp_cfg, sizeof(idev->mlp->mp_cfg));
r = set_arg(arg, &inl_ppp->mp_cfg, sizeof(inl_ppp->mp_cfg));
break;
case PPPIOCSMPFLAGS: /* set configuration flags */
r = get_arg(arg, &val, sizeof(val));
if (r)
break;
idev->mlp->mp_cfg = val;
inl_ppp->mp_cfg = val;
break;
case PPPIOCGFLAGS: /* get configuration flags */
cfg = idev->pppcfg | ippp_ccp_get_flags(idev->ccp);
cfg = ind_ppp->pppcfg | ippp_ccp_get_flags(ind_ppp->ccp);
r = set_arg(arg, &cfg, sizeof(cfg));
break;
case PPPIOCSFLAGS: /* set configuration flags */
r = get_arg(arg, &val, sizeof(val));
if (r)
break;
if ((val & SC_ENABLE_IP) && !(idev->pppcfg & SC_ENABLE_IP)) {
idev->pppcfg = val;
if ((val & SC_ENABLE_IP) && !(ind_ppp->pppcfg & SC_ENABLE_IP)) {
ind_ppp->pppcfg = val;
/* OK .. we are ready to send buffers */
isdn_net_online(idev);
break;
}
idev->pppcfg = val;
ind_ppp->pppcfg = val;
break;
case PPPIOCGIDLE: /* get idle time information */
{
......@@ -431,7 +440,7 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
r = get_arg(arg, &val, sizeof(val));
if (r)
break;
r = ippp_ccp_set_mru(idev->ccp, val);
r = ippp_ccp_set_mru(ind_ppp->ccp, val);
break;
case PPPIOCSMPMRU:
break;
......@@ -580,13 +589,13 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot
}
void
ippp_push_proto(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto)
{
if (skb_headroom(skb) < 2) {
isdn_BUG();
return;
}
if ((idev->pppcfg & SC_COMP_PROT) && proto <= 0xff)
if ((ind_ppp->pppcfg & SC_COMP_PROT) && proto <= 0xff)
put_u8(skb_push(skb, 1), proto);
else
put_u16(skb_push(skb, 2), proto);
......@@ -594,7 +603,7 @@ ippp_push_proto(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
}
static void
ippp_push_ac(isdn_net_dev *idev, struct sk_buff *skb)
ippp_push_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb)
{
unsigned char *p;
......@@ -602,7 +611,7 @@ ippp_push_ac(isdn_net_dev *idev, struct sk_buff *skb)
isdn_BUG();
return;
}
if (idev->pppcfg & SC_COMP_AC)
if (ind_ppp->pppcfg & SC_COMP_AC)
return;
p = skb_push(skb, 2);
......@@ -618,13 +627,13 @@ ippp_push_ac(isdn_net_dev *idev, struct sk_buff *skb)
static void
isdn_ppp_unbind(isdn_net_dev *idev)
{
struct ipppd *is = idev->ipppd;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *is = ind_ppp->ipppd;
if (!is) {
isdn_BUG();
return;
}
ipppd_debug(is, "");
if (is->state != IPPPD_ST_ASSIGNED)
......@@ -633,12 +642,15 @@ isdn_ppp_unbind(isdn_net_dev *idev)
is->state = IPPPD_ST_OPEN;
/* is->idev will be invalid shortly */
ippp_ccp_free(idev->ccp);
ippp_ccp_free(ind_ppp->ccp);
is->idev = NULL;
/* lose the reference we took on isdn_ppp_bind */
ipppd_put(is);
idev->ipppd = NULL;
ind_ppp->ipppd = NULL;
kfree(ind_ppp);
idev->ind_priv = NULL;
return;
}
......@@ -649,15 +661,19 @@ isdn_ppp_unbind(isdn_net_dev *idev)
int
isdn_ppp_bind(isdn_net_dev *idev)
{
struct ind_ppp *ind_ppp;
int unit = 0;
unsigned long flags;
int retval = 0;
struct ipppd *ipppd;
if (idev->ipppd) {
if (idev->ind_priv) {
isdn_BUG();
return 0;
return -EIO;
}
ind_ppp = kmalloc(sizeof(struct ind_ppp), GFP_KERNEL);
if (!ind_ppp)
return -ENOMEM;
spin_lock_irqsave(&ipppds_lock, flags);
if (idev->pppbind < 0) { /* device bound to ippp device ? */
......@@ -709,21 +725,22 @@ isdn_ppp_bind(isdn_net_dev *idev)
ipppd->state = IPPPD_ST_ASSIGNED;
ipppd->idev = idev;
/* we hold a reference until isdn_ppp_unbind() */
idev->ipppd = ipppd_get(ipppd);
ipppd_get(ipppd);
spin_unlock_irqrestore(&ipppds_lock, flags);
idev->pppcfg = 0; /* config flags */
idev->ccp = ippp_ccp_alloc();
if (!idev->ccp) {
idev->ind_priv = ind_ppp;
ind_ppp->pppcfg = 0; /* config flags */
ind_ppp->ipppd = ipppd;
ind_ppp->ccp = ippp_ccp_alloc();
if (!ind_ppp->ccp) {
retval = -ENOMEM;
goto out;
}
idev->ccp->proto = PPP_COMPFRAG;
idev->ccp->priv = idev;
idev->ccp->alloc_skb = isdn_ppp_dev_alloc_skb;
idev->ccp->xmit = isdn_ppp_dev_xmit;
idev->ccp->kick_up = isdn_ppp_dev_kick_up;
ind_ppp->ccp->proto = PPP_COMPFRAG;
ind_ppp->ccp->priv = idev;
ind_ppp->ccp->alloc_skb = isdn_ppp_dev_alloc_skb;
ind_ppp->ccp->xmit = isdn_ppp_dev_xmit;
ind_ppp->ccp->kick_up = isdn_ppp_dev_kick_up;
retval = ippp_mp_bind(idev);
if (retval)
......@@ -732,13 +749,16 @@ isdn_ppp_bind(isdn_net_dev *idev)
return 0;
out:
idev->ipppd->state = IPPPD_ST_OPEN;
ipppd_put(idev->ipppd);
idev->ipppd = NULL;
ipppd->state = IPPPD_ST_OPEN;
ipppd_put(ipppd);
ind_ppp->ipppd = NULL;
kfree(ind_ppp);
idev->ind_priv = NULL;
return retval;
err:
spin_unlock_irqrestore(&ipppds_lock, flags);
kfree(ind_ppp);
return retval;
}
......@@ -750,7 +770,8 @@ isdn_ppp_bind(isdn_net_dev *idev)
static void
isdn_ppp_connected(isdn_net_dev *idev)
{
struct ipppd *ipppd = idev->ipppd;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *ipppd = ind_ppp->ipppd;
ipppd_debug(ipppd, "");
......@@ -762,11 +783,12 @@ isdn_ppp_connected(isdn_net_dev *idev)
static void
isdn_ppp_disconnected(isdn_net_dev *idev)
{
struct ipppd *ipppd = idev->ipppd;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *ipppd = ind_ppp->ipppd;
ipppd_debug(ipppd, "");
if (idev->pppcfg & SC_ENABLE_IP)
if (ind_ppp->pppcfg & SC_ENABLE_IP)
isdn_net_offline(idev);
if (ipppd->state != IPPPD_ST_CONNECTED)
......@@ -799,7 +821,7 @@ isdn_ppp_cleanup(void)
* retval != 0 -> discard packet silently
*/
static int
isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
isdn_ppp_skip_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb)
{
u8 val;
......@@ -810,7 +832,7 @@ isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
if (val != PPP_ALLSTATIONS) {
/* if AC compression was not negotiated, but no AC present,
discard packet */
if (idev->pppcfg & SC_REJ_COMP_AC)
if (ind_ppp->pppcfg & SC_REJ_COMP_AC)
return -EINVAL;
return 0;
......@@ -859,10 +881,10 @@ isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto)
static void
isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, struct sk_buff *skb)
{
struct ipppd *is;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *is = ind_ppp->ipppd;
u16 proto;
is = idev->ipppd;
if (!is)
goto err;
......@@ -872,7 +894,7 @@ isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, struct sk_buff *skb)
isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1);
}
if (isdn_ppp_skip_ac(idev, skb) < 0)
if (isdn_ppp_skip_ac(ind_ppp, skb) < 0)
goto err;
if (isdn_ppp_strip_proto(skb, &proto))
......@@ -887,22 +909,22 @@ isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, struct sk_buff *skb)
}
/*
* we receive a reassembled frame, MPPP has been taken care of before.
* address/control and protocol have been stripped from the skb
* note: net_dev has to be master net_dev
*/
void
ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
{
isdn_net_local *lp = idev->mlp;
struct ipppd *is = idev->ipppd;
struct inl_ppp *inl_ppp = lp->inl_priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *is = ind_ppp->ipppd;
if (is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
isdn_ppp_frame_log("rpush", skb->data, skb->len, 256, is->unit, -1);
}
/* all packets need to be passed through the compressor */
skb = ippp_ccp_decompress(lp->ccp, skb, &proto);
skb = ippp_ccp_decompress(inl_ppp->ccp, skb, &proto);
if (!skb) /* decompression error */
goto error;
......@@ -926,10 +948,10 @@ ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
ippp_vj_decompress(idev, skb, proto);
break;
case PPP_CCPFRAG:
ippp_ccp_receive_ccp(idev->ccp, skb);
ippp_ccp_receive_ccp(ind_ppp->ccp, skb);
goto ccp;
case PPP_CCP:
ippp_ccp_receive_ccp(lp->ccp, skb);
ippp_ccp_receive_ccp(inl_ppp->ccp, skb);
ccp:
/* Dont pop up ResetReq/Ack stuff to the daemon any
longer - the job is done already */
......@@ -966,6 +988,8 @@ static int
isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
isdn_net_local *mlp = ndev->priv;
struct inl_ppp *inl_ppp = mlp->inl_priv;
struct ind_ppp *ind_ppp;
isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
u16 proto = PPP_IP; /* 0x21 */
struct ipppd *ipppd;
......@@ -993,11 +1017,12 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
goto stop;
}
if (!(idev->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
ind_ppp = idev->ind_priv;
if (!(ind_ppp->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
isdn_BUG();
goto stop;
}
ipppd = idev->ipppd;
ipppd = ind_ppp->ipppd;
idev->huptimer = 0;
if (ipppd->debug & 0x40)
......@@ -1007,12 +1032,12 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
skb = ippp_vj_compress(idev, skb, &proto);
/* normal (single link) or bundle compression */
skb = ippp_ccp_compress(mlp->ccp, skb, &proto);
skb = ippp_ccp_compress(inl_ppp->ccp, skb, &proto);
if (ipppd->debug & 0x40)
isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
ippp_push_proto(idev, skb, proto);
ippp_push_proto(ind_ppp, skb, proto);
ippp_mp_xmit(idev, skb, proto);
return 0;
......@@ -1029,9 +1054,10 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
void
ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
{
struct ipppd *ipppd = idev->ipppd;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct ipppd *ipppd = ind_ppp->ipppd;
ippp_push_ac(idev, skb);
ippp_push_ac(ind_ppp, skb);
if (ipppd->debug & 0x40) {
isdn_ppp_frame_log("xmit3", skb->data, skb->len, 32, ipppd->unit, -1);
......@@ -1049,6 +1075,7 @@ isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev)
{
struct ppp_stats *res, t;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
struct inl_ppp *inl_ppp = lp->inl_priv;
struct slcompress *slcomp;
int err;
......@@ -1069,7 +1096,7 @@ isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev)
t.p.ppp_obytes = lp->stats.tx_bytes;
t.p.ppp_oerrors = lp->stats.tx_errors;
#ifdef CONFIG_ISDN_PPP_VJ
slcomp = lp->slcomp;
slcomp = inl_ppp->slcomp;
if (slcomp) {
t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
t.vj.vjs_compressed = slcomp->sls_o_compressed;
......@@ -1152,21 +1179,24 @@ isdn_ppp_if_get_unit(char *name)
static void isdn_ppp_dev_kick_up(void *priv)
{
isdn_net_dev *idev = priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
ipppd_queue_read(idev->ipppd, PPP_COMPFRAG, NULL, 0);
ipppd_queue_read(ind_ppp->ipppd, PPP_COMPFRAG, NULL, 0);
}
static void isdn_ppp_lp_kick_up(void *priv)
{
isdn_net_local *lp = priv;
isdn_net_dev *idev;
struct ind_ppp *ind_ppp;
if (list_empty(&lp->online)) {
isdn_BUG();
return;
}
idev = list_entry(lp->online.next, isdn_net_dev, online);
ipppd_queue_read(idev->ipppd, PPP_COMP, NULL, 0);
ind_ppp = idev->ind_priv;
ipppd_queue_read(ind_ppp->ipppd, PPP_COMP, NULL, 0);
}
/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
......@@ -1211,9 +1241,10 @@ static void
isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb, u16 proto)
{
isdn_net_dev *idev = priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
ippp_push_proto(idev, skb, proto);
ippp_push_ac(idev, skb);
ippp_push_proto(ind_ppp, skb, proto);
ippp_push_ac(ind_ppp, skb);
isdn_net_write_super(idev, skb);
}
......@@ -1222,14 +1253,16 @@ isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb, u16 proto)
{
isdn_net_local *lp = priv;
isdn_net_dev *idev;
struct ind_ppp *ind_ppp;
if (list_empty(&lp->online)) {
isdn_BUG();
return;
}
idev = list_entry(lp->online.next, isdn_net_dev, online);
ippp_push_proto(idev, skb, proto);
ippp_push_ac(idev, skb);
ind_ppp = idev->ind_priv;
ippp_push_proto(ind_ppp, skb, proto);
ippp_push_ac(ind_ppp, skb);
isdn_net_write_super(idev, skb);
}
......@@ -1237,13 +1270,15 @@ static int
isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data)
{
struct ippp_ccp *ccp;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
if (data->flags & IPPP_COMP_FLAG_LINK)
ccp = idev->ccp;
ccp = ind_ppp->ccp;
else
ccp = idev->mlp->ccp;
ccp = inl_ppp->ccp;
return ippp_ccp_set_compressor(ccp, idev->ipppd->unit, data);
return ippp_ccp_set_compressor(ccp, ind_ppp->ipppd->unit, data);
}
// ISDN_NET_ENCAP_SYNCPPP
......@@ -1252,37 +1287,48 @@ isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data)
static int
isdn_ppp_open(isdn_net_local *lp)
{
lp->slcomp = ippp_vj_alloc();
if (!lp->slcomp)
struct inl_ppp *inl_ppp;
inl_ppp = kmalloc(sizeof(*inl_ppp), GFP_KERNEL);
if (!inl_ppp)
return -ENOMEM;
lp->inl_priv = inl_ppp;
inl_ppp->slcomp = ippp_vj_alloc();
if (!inl_ppp->slcomp)
goto err;
lp->ccp = ippp_ccp_alloc();
if (!lp->ccp)
inl_ppp->ccp = ippp_ccp_alloc();
if (!inl_ppp->ccp)
goto err_vj;
lp->ccp->proto = PPP_COMP;
lp->ccp->priv = lp;
lp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb;
lp->ccp->xmit = isdn_ppp_lp_xmit;
lp->ccp->kick_up = isdn_ppp_lp_kick_up;
inl_ppp->ccp->proto = PPP_COMP;
inl_ppp->ccp->priv = lp;
inl_ppp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb;
inl_ppp->ccp->xmit = isdn_ppp_lp_xmit;
inl_ppp->ccp->kick_up = isdn_ppp_lp_kick_up;
return 0;
err_vj:
ippp_vj_free(lp->slcomp);
lp->slcomp = NULL;
ippp_vj_free(inl_ppp->slcomp);
err:
kfree(inl_ppp);
lp->inl_priv = NULL;
return -ENOMEM;
}
static void
isdn_ppp_close(isdn_net_local *lp)
{
struct inl_ppp *inl_ppp = lp->inl_priv;
ippp_ccp_free(lp->ccp);
lp->ccp = NULL;
ippp_vj_free(lp->slcomp);
lp->slcomp = NULL;
ippp_ccp_free(inl_ppp->ccp);
ippp_vj_free(inl_ppp->slcomp);
kfree(inl_ppp);
lp->inl_priv = NULL;
}
struct isdn_netif_ops isdn_ppp_ops = {
......
......@@ -17,6 +17,24 @@ void isdn_ppp_cleanup(void);
int isdn_ppp_dial_slave(char *);
int isdn_ppp_hangup_slave(char *);
struct inl_ppp {
unsigned long debug;
struct slcompress *slcomp;
struct ippp_ccp *ccp; /* CCP for this channel */
unsigned int mp_cfg;
struct sk_buff_head mp_frags; /* fragments list */
u32 mp_rxseq; /* last processed packet seq # */
u32 mp_txseq; /* current tx seq # */
};
struct ind_ppp {
struct ipppd *ipppd; /* /dev/ipppX which controls us */
unsigned int pppcfg;
unsigned long debug;
struct ippp_ccp *ccp; /* CCP for this channel (multilink) */
u32 mp_rxseq; /* last seq no seen on this channel */
};
void
isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,
int unit, int slot);
......@@ -25,7 +43,7 @@ int
isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto);
void
ippp_push_proto(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto);
void
ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
......
......@@ -27,20 +27,21 @@
int
ippp_mp_bind(isdn_net_dev *idev)
{
isdn_net_local *lp = idev->mlp;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
/* seq no last seen, maybe set to bundle min, when joining? */
idev->mp_rxseq = 0;
ind_ppp->mp_rxseq = 0;
if (!list_empty(&lp->online))
if (!list_empty(&idev->mlp->online))
return 0;
/* first channel for this link, do some setup */
lp->mp_cfg = 0; /* MPPP configuration */
lp->mp_txseq = 0; /* MPPP tx sequence number */
lp->mp_rxseq = (u32) -1;
skb_queue_head_init(&lp->mp_frags);
inl_ppp->mp_cfg = 0; /* MPPP configuration */
inl_ppp->mp_txseq = 0; /* MPPP tx sequence number */
inl_ppp->mp_rxseq = (u32) -1;
skb_queue_head_init(&inl_ppp->mp_frags);
return 0;
}
......@@ -51,6 +52,7 @@ ippp_mp_bundle(isdn_net_dev *idev, int unit)
isdn_net_local *lp = idev->mlp;
char ifn[IFNAMSIZ + 1];
isdn_net_dev *n_idev;
struct ind_ppp *ind_ppp;
printk(KERN_DEBUG "%s: %s: slave unit: %d\n",
__FUNCTION__, idev->name, unit);
......@@ -65,11 +67,12 @@ ippp_mp_bundle(isdn_net_dev *idev, int unit)
return -ENODEV;
found:
if (!n_idev->ipppd) {
ind_ppp = n_idev->ind_priv;
if (!ind_ppp->ipppd) {
printk(KERN_INFO "%s: no ipppd?\n", __FUNCTION__);
return -ENXIO;
}
n_idev->pppcfg |= SC_ENABLE_IP;
ind_ppp->pppcfg |= SC_ENABLE_IP;
isdn_net_online(n_idev);
return 0;
......@@ -78,32 +81,33 @@ ippp_mp_bundle(isdn_net_dev *idev, int unit)
void
ippp_mp_disconnected(isdn_net_dev *idev)
{
isdn_net_local *lp = idev->mlp;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
if (!list_empty(&lp->online))
if (!list_empty(&idev->mlp->online))
return;
/* we're the last link going down */
skb_queue_purge(&lp->mp_frags);
skb_queue_purge(&inl_ppp->mp_frags);
}
void
ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
{
isdn_net_local *lp = idev->mlp;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
unsigned char *p;
long txseq;
if (!(lp->mp_cfg & SC_MP_PROT)) {
if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
return ippp_xmit(idev, skb);
}
/* we could do something smarter than just sending
* the complete packet as fragment... */
txseq = lp->mp_txseq++;
txseq = inl_ppp->mp_txseq++;
if (lp->mp_cfg & SC_OUT_SHORT_SEQ) {
if (inl_ppp->mp_cfg & SC_OUT_SHORT_SEQ) {
/* sequence number: 12bit */
p = skb_push(skb, 2);
p[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((txseq >> 8) & 0xf);
......@@ -117,8 +121,8 @@ ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
p[3] = (txseq >> 0) & 0xff;
}
proto = PPP_MP;
skb = ippp_ccp_compress(idev->ccp, skb, &proto);
ippp_push_proto(idev, skb, proto);
skb = ippp_ccp_compress(ind_ppp->ccp, skb, &proto);
ippp_push_proto(ind_ppp, skb, proto);
ippp_xmit(idev, skb);
}
......@@ -127,12 +131,13 @@ static void mp_receive(isdn_net_dev *idev, struct sk_buff *skb);
void
ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
{
isdn_net_local *lp = idev->mlp;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
if (lp->mp_cfg & SC_REJ_MP_PROT)
if (inl_ppp->mp_cfg & SC_REJ_MP_PROT)
goto out;
skb = ippp_ccp_decompress(idev->ccp, skb, &proto);
skb = ippp_ccp_decompress(ind_ppp->ccp, skb, &proto);
if (!skb)
goto drop;
......@@ -143,7 +148,7 @@ ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
return ippp_receive(idev, skb, proto);
drop:
lp->stats.rx_errors++;
idev->mlp->stats.rx_errors++;
kfree_skb(skb);
}
......@@ -257,9 +262,10 @@ mp_complete_seq(isdn_net_local *lp, struct sk_buff *b, struct sk_buff *e)
struct sk_buff *
mp_reassemble(isdn_net_local *lp)
{
struct sk_buff_head *frags = &lp->mp_frags;
struct inl_ppp *inl_ppp = lp->inl_priv;
struct sk_buff_head *frags = &inl_ppp->mp_frags;
struct sk_buff *p, *n, *pp, *start;
u32 min_seq = lp->mp_rxseq;
u32 min_seq = inl_ppp->mp_rxseq;
u32 next_seq = 0;
again:
......@@ -307,32 +313,35 @@ static void
mp_receive(isdn_net_dev *idev, struct sk_buff *skb)
{
isdn_net_local *lp = idev->mlp;
struct inl_ppp *inl_ppp = lp->inl_priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
isdn_net_dev *qdev;
struct sk_buff_head *frags = &lp->mp_frags;
struct sk_buff_head *frags = &inl_ppp->mp_frags;
u32 seq;
u16 proto;
print_recv_pkt(-1, skb);
if (skb->len < (lp->mp_cfg & SC_IN_SHORT_SEQ ? 2 : 4))
if (skb->len < (inl_ppp->mp_cfg & SC_IN_SHORT_SEQ ? 2 : 4))
goto drop;
seq = get_seq(skb, idev->mp_rxseq, lp->mp_cfg & SC_IN_SHORT_SEQ);
idev->mp_rxseq = seq;
seq = get_seq(skb, ind_ppp->mp_rxseq, inl_ppp->mp_cfg & SC_IN_SHORT_SEQ);
ind_ppp->mp_rxseq = seq;
if (lp->mp_rxseq == (u32) -1) {
if (inl_ppp->mp_rxseq == (u32) -1) {
/* first packet */
lp->mp_rxseq = seq;
inl_ppp->mp_rxseq = seq;
}
if (MP_LT(seq, lp->mp_rxseq)) {
if (MP_LT(seq, inl_ppp->mp_rxseq)) {
goto drop;
}
/* Find the minimum sequence number received over all channels.
* No fragments with numbers lower than this will arrive later. */
lp->mp_rxseq = seq;
inl_ppp->mp_rxseq = seq;
list_for_each_entry(qdev, &lp->online, online) {
if (MP_LT(qdev->mp_rxseq, lp->mp_rxseq))
lp->mp_rxseq = qdev->mp_rxseq;
struct ind_ppp *ind_ppp = qdev->ind_priv;
if (MP_LT(ind_ppp->mp_rxseq, inl_ppp->mp_rxseq))
inl_ppp->mp_rxseq = ind_ppp->mp_rxseq;
}
/* Insert the skb into the list of received fragments, ordered by
......
......@@ -27,23 +27,25 @@ ippp_vj_free(struct slcompress *slcomp)
int
ippp_vj_set_maxcid(isdn_net_dev *idev, int val)
{
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
struct slcompress *sltmp;
sltmp = slhc_init(16, val + 1);
if (!sltmp)
return -ENOMEM;
if (idev->mlp->slcomp)
slhc_free(idev->mlp->slcomp);
if (inl_ppp->slcomp)
slhc_free(inl_ppp->slcomp);
idev->mlp->slcomp = sltmp;
inl_ppp->slcomp = sltmp;
return 0;
}
void
ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto)
{
struct slcompress *slcomp = idev->mlp->slcomp;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
struct slcompress *slcomp = inl_ppp->slcomp;
struct sk_buff *skb;
int len;
......@@ -84,11 +86,14 @@ ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto)
struct sk_buff *
ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
{
struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
struct ind_ppp *ind_ppp = idev->ind_priv;
struct slcompress *slcomp = inl_ppp->slcomp;
struct sk_buff *skb;
unsigned char *buf;
int len;
if (!(idev->pppcfg & SC_COMP_TCP) || *proto != PPP_IP)
if (!(ind_ppp->pppcfg & SC_COMP_TCP) || *proto != PPP_IP)
return skb_old;
skb = isdn_ppp_dev_alloc_skb(idev, skb_old->len, GFP_ATOMIC);
......@@ -97,8 +102,9 @@ ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
skb_put(skb, skb_old->len);
buf = skb_old->data;
len = slhc_compress(idev->mlp->slcomp, skb_old->data, skb_old->len,
skb->data, &buf, !(idev->pppcfg & SC_NO_TCP_CCID));
// FIXME flag should be per bundle
len = slhc_compress(slcomp, skb_old->data, skb_old->len, skb->data,
&buf, !(ind_ppp->pppcfg & SC_NO_TCP_CCID));
if (buf == skb_old->data) {
kfree_skb(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment