Commit e7288954 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: alloc CISCO HDLC info dynamically

There's really no need to allocate private storage for all possible
interface types, just leave it to the interface type to alloc the memory
it needs.
  
CISCO HDLC does that, now.
parent 4266ccb5
...@@ -55,6 +55,7 @@ static int ...@@ -55,6 +55,7 @@ static int
isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
isdn_net_local *mlp = dev->priv; isdn_net_local *mlp = dev->priv;
struct inl_cisco *cisco = mlp->inl_priv;
unsigned long len = 0; unsigned long len = 0;
int period; int period;
char debserint; char debserint;
...@@ -66,13 +67,13 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -66,13 +67,13 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
switch (cmd) { switch (cmd) {
/* get/set keepalive period */ /* get/set keepalive period */
case SIOCGKEEPPERIOD: case SIOCGKEEPPERIOD:
len = sizeof(mlp->cisco_keepalive_period); len = sizeof(cisco->keepalive_period);
if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
(char *)&mlp->cisco_keepalive_period, len)) (char *)&cisco->keepalive_period, len))
rc = -EFAULT; rc = -EFAULT;
break; break;
case SIOCSKEEPPERIOD: case SIOCSKEEPPERIOD:
len = sizeof(mlp->cisco_keepalive_period); len = sizeof(cisco->keepalive_period);
if (copy_from_user((char *)&period, if (copy_from_user((char *)&period,
(char *)ifr->ifr_ifru.ifru_data, len)) { (char *)ifr->ifr_ifru.ifru_data, len)) {
rc = -EFAULT; rc = -EFAULT;
...@@ -82,21 +83,21 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -82,21 +83,21 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
rc = -EINVAL; rc = -EINVAL;
break; break;
} }
mod_timer(&mlp->cisco_timer, jiffies + period * HZ); mod_timer(&cisco->timer, jiffies + period * HZ);
printk(KERN_INFO "%s: Keepalive period set " printk(KERN_INFO "%s: Keepalive period set "
"to %d seconds.\n", dev->name, period); "to %d seconds.\n", dev->name, period);
mlp->cisco_keepalive_period = period; cisco->keepalive_period = period;
break; break;
/* get/set debugging */ /* get/set debugging */
case SIOCGDEBSERINT: case SIOCGDEBSERINT:
len = sizeof(mlp->cisco_debserint); len = sizeof(cisco->debserint);
if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
(char *)&mlp->cisco_debserint, len)) (char *)&cisco->debserint, len))
rc = -EFAULT; rc = -EFAULT;
break; break;
case SIOCSDEBSERINT: case SIOCSDEBSERINT:
len = sizeof(mlp->cisco_debserint); len = sizeof(cisco->debserint);
if (copy_from_user((char *)&debserint, if (copy_from_user((char *)&debserint,
(char *)ifr->ifr_ifru.ifru_data, len)) { (char *)ifr->ifr_ifru.ifru_data, len)) {
rc = -EFAULT; rc = -EFAULT;
...@@ -106,7 +107,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -106,7 +107,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
rc = -EINVAL; rc = -EINVAL;
break; break;
} }
mlp->cisco_debserint = debserint; cisco->debserint = debserint;
break; break;
default: default:
...@@ -121,10 +122,11 @@ static void ...@@ -121,10 +122,11 @@ static void
isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
{ {
isdn_net_local *mlp = (isdn_net_local *) data; isdn_net_local *mlp = (isdn_net_local *) data;
isdn_net_dev *idev; isdn_net_dev *idev;
struct inl_cisco *cisco = mlp->inl_priv;
struct sk_buff *skb; struct sk_buff *skb;
unsigned char *p; unsigned char *p;
unsigned long last_cisco_myseq = mlp->cisco_myseq; unsigned long last_cisco_myseq = cisco->myseq;
int myseq_diff = 0; int myseq_diff = 0;
if (list_empty(&mlp->online)) { if (list_empty(&mlp->online)) {
...@@ -132,33 +134,33 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) ...@@ -132,33 +134,33 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
return; return;
} }
idev = list_entry(mlp->online.next, isdn_net_dev, online); idev = list_entry(mlp->online.next, isdn_net_dev, online);
mlp->cisco_myseq++; cisco->myseq++;
myseq_diff = (mlp->cisco_myseq - mlp->cisco_mineseen); myseq_diff = cisco->myseq - cisco->mineseen;
if (mlp->cisco_line_state && (myseq_diff >= 3 || myseq_diff <= -3)) { if (cisco->line_state && (myseq_diff >= 3 || myseq_diff <= -3)) {
/* line up -> down */ /* line up -> down */
mlp->cisco_line_state = 0; cisco->line_state = 0;
printk (KERN_WARNING printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s," "UPDOWN: Line protocol on Interface %s,"
" changed state to down\n", idev->name); " changed state to down\n", idev->name);
/* should stop routing higher-level data accross */ /* should stop routing higher-level data accross */
} else if (!mlp->cisco_line_state && } else if (!cisco->line_state &&
myseq_diff >= 0 && myseq_diff <= 2) { myseq_diff >= 0 && myseq_diff <= 2) {
/* line down -> up */ /* line down -> up */
mlp->cisco_line_state = 1; cisco->line_state = 1;
printk (KERN_WARNING printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s," "UPDOWN: Line protocol on Interface %s,"
" changed state to up\n", idev->name); " changed state to up\n", idev->name);
/* restart routing higher-level data accross */ /* restart routing higher-level data accross */
} }
if (mlp->cisco_debserint) if (cisco->debserint)
printk (KERN_DEBUG "%s: HDLC " printk (KERN_DEBUG "%s: HDLC "
"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n", "myseq %u, mineseen %u%c, yourseen %u, %s\n",
idev->name, last_cisco_myseq, mlp->cisco_mineseen, idev->name, cisco->myseq, cisco->mineseen,
(last_cisco_myseq == mlp->cisco_mineseen) ? '*' : 040, (last_cisco_myseq == cisco->mineseen) ? '*' : 040,
mlp->cisco_yourseq, cisco->yourseq,
(mlp->cisco_line_state) ? "line up" : "line down"); (cisco->line_state) ? "line up" : "line down");
skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
if (!skb) if (!skb)
...@@ -173,13 +175,13 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) ...@@ -173,13 +175,13 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
/* slarp keepalive */ /* slarp keepalive */
p += put_u32(p, CISCO_SLARP_KEEPALIVE); p += put_u32(p, CISCO_SLARP_KEEPALIVE);
p += put_u32(p, mlp->cisco_myseq); p += put_u32(p, cisco->myseq);
p += put_u32(p, mlp->cisco_yourseq); p += put_u32(p, cisco->yourseq);
p += put_u16(p, 0xffff); // reliablity, always 0xffff p += put_u16(p, 0xffff); // reliablity, always 0xffff
isdn_net_write_super(idev, skb); isdn_net_write_super(idev, skb);
mod_timer(&mlp->cisco_timer, jiffies + mlp->cisco_keepalive_period * HZ); mod_timer(&cisco->timer, jiffies + cisco->keepalive_period * HZ);
} }
static void static void
...@@ -219,24 +221,25 @@ static void ...@@ -219,24 +221,25 @@ static void
isdn_ciscohdlck_connected(isdn_net_dev *idev) isdn_ciscohdlck_connected(isdn_net_dev *idev)
{ {
isdn_net_local *lp = idev->mlp; isdn_net_local *lp = idev->mlp;
struct inl_cisco *cisco = lp->inl_priv;
lp->cisco_myseq = 0; cisco->myseq = 0;
lp->cisco_mineseen = 0; cisco->mineseen = 0;
lp->cisco_yourseq = 0; cisco->yourseq = 0;
lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT; cisco->keepalive_period = ISDN_TIMER_KEEPINT;
lp->cisco_last_slarp_in = 0; cisco->last_slarp_in = 0;
lp->cisco_line_state = 0; cisco->line_state = 0;
lp->cisco_debserint = 0; cisco->debserint = 0;
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) {
/* send slarp request because interface/seq.no.s reset */ /* send slarp request because interface/seq.no.s reset */
isdn_net_ciscohdlck_slarp_send_request(lp); isdn_net_ciscohdlck_slarp_send_request(lp);
init_timer(&lp->cisco_timer); init_timer(&cisco->timer);
lp->cisco_timer.data = (unsigned long) lp; cisco->timer.data = (unsigned long) lp;
lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive; cisco->timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ; cisco->timer.expires = jiffies + cisco->keepalive_period * HZ;
add_timer(&lp->cisco_timer); add_timer(&cisco->timer);
} }
netif_wake_queue(&lp->dev); netif_wake_queue(&lp->dev);
} }
...@@ -245,9 +248,10 @@ static void ...@@ -245,9 +248,10 @@ static void
isdn_ciscohdlck_disconnected(isdn_net_dev *idev) isdn_ciscohdlck_disconnected(isdn_net_dev *idev)
{ {
isdn_net_local *lp = idev->mlp; isdn_net_local *lp = idev->mlp;
struct inl_cisco *cisco = lp->inl_priv;
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) {
del_timer(&lp->cisco_timer); del_timer(&cisco->timer);
} }
} }
...@@ -295,6 +299,7 @@ static void ...@@ -295,6 +299,7 @@ static void
isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb)
{ {
isdn_net_local *mlp = idev->mlp; isdn_net_local *mlp = idev->mlp;
struct inl_cisco *cisco = mlp->inl_priv;
unsigned char *p; unsigned char *p;
int period; int period;
u32 code; u32 code;
...@@ -311,7 +316,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) ...@@ -311,7 +316,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb)
switch (code) { switch (code) {
case CISCO_SLARP_REQUEST: case CISCO_SLARP_REQUEST:
mlp->cisco_yourseq = 0; cisco->yourseq = 0;
isdn_net_ciscohdlck_slarp_send_reply(idev); isdn_net_ciscohdlck_slarp_send_reply(idev);
break; break;
case CISCO_SLARP_REPLY: case CISCO_SLARP_REPLY:
...@@ -338,21 +343,20 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) ...@@ -338,21 +343,20 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb)
HIPQUAD(addr), HIPQUAD(mask)); HIPQUAD(addr), HIPQUAD(mask));
break; break;
case CISCO_SLARP_KEEPALIVE: case CISCO_SLARP_KEEPALIVE:
period = (int)((jiffies - mlp->cisco_last_slarp_in period = (jiffies - cisco->last_slarp_in + HZ/2 - 1) / HZ;
+ HZ/2 - 1) / HZ); if (cisco->debserint &&
if (mlp->cisco_debserint && (period != cisco->keepalive_period) &&
(period != mlp->cisco_keepalive_period) && cisco->last_slarp_in) {
mlp->cisco_last_slarp_in) {
printk(KERN_DEBUG "%s: Keepalive period mismatch - " printk(KERN_DEBUG "%s: Keepalive period mismatch - "
"is %d but should be %d.\n", "is %d but should be %d.\n",
idev->name, period, mlp->cisco_keepalive_period); idev->name, period, cisco->keepalive_period);
} }
mlp->cisco_last_slarp_in = jiffies; cisco->last_slarp_in = jiffies;
p += get_u32(p, &my_seq); p += get_u32(p, &my_seq);
p += get_u32(p, &your_seq); p += get_u32(p, &your_seq);
p += get_u16(p, &unused); p += get_u16(p, &unused);
mlp->cisco_yourseq = my_seq; cisco->yourseq = my_seq;
mlp->cisco_mineseen = your_seq; cisco->mineseen = your_seq;
break; break;
} }
} }
...@@ -361,6 +365,7 @@ static void ...@@ -361,6 +365,7 @@ static void
isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct inl_cisco *cisco = lp->inl_priv;
unsigned char *p; unsigned char *p;
u8 addr; u8 addr;
u8 ctrl; u8 ctrl;
...@@ -387,7 +392,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -387,7 +392,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
isdn_net_ciscohdlck_slarp_in(idev, skb); isdn_net_ciscohdlck_slarp_in(idev, skb);
goto out_free; goto out_free;
case CISCO_TYPE_CDP: case CISCO_TYPE_CDP:
if (lp->cisco_debserint) if (cisco->debserint)
printk(KERN_DEBUG "%s: Received CDP packet. use " printk(KERN_DEBUG "%s: Received CDP packet. use "
"\"no cdp enable\" on cisco.\n", idev->name); "\"no cdp enable\" on cisco.\n", idev->name);
goto out_free; goto out_free;
...@@ -417,6 +422,22 @@ isdn_ciscohdlck_header(struct sk_buff *skb, struct net_device *dev, ...@@ -417,6 +422,22 @@ isdn_ciscohdlck_header(struct sk_buff *skb, struct net_device *dev,
return 4; return 4;
} }
static int
isdn_ciscohdlck_open(isdn_net_local *lp)
{
lp->inl_priv = kmalloc(sizeof(struct inl_cisco), GFP_KERNEL);
if (!lp->inl_priv)
return -ENOMEM;
return 0;
}
static void
isdn_ciscohdlck_close(isdn_net_local *lp)
{
kfree(lp->inl_priv);
}
struct isdn_netif_ops isdn_ciscohdlck_ops = { struct isdn_netif_ops isdn_ciscohdlck_ops = {
.hard_start_xmit = isdn_net_start_xmit, .hard_start_xmit = isdn_net_start_xmit,
.hard_header = isdn_ciscohdlck_header, .hard_header = isdn_ciscohdlck_header,
...@@ -426,4 +447,6 @@ struct isdn_netif_ops isdn_ciscohdlck_ops = { ...@@ -426,4 +447,6 @@ struct isdn_netif_ops isdn_ciscohdlck_ops = {
.receive = isdn_ciscohdlck_receive, .receive = isdn_ciscohdlck_receive,
.connected = isdn_ciscohdlck_connected, .connected = isdn_ciscohdlck_connected,
.disconnected = isdn_ciscohdlck_disconnected, .disconnected = isdn_ciscohdlck_disconnected,
.open = isdn_ciscohdlck_open,
.close = isdn_ciscohdlck_close,
}; };
...@@ -12,4 +12,15 @@ ...@@ -12,4 +12,15 @@
extern struct isdn_netif_ops isdn_ciscohdlck_ops; extern struct isdn_netif_ops isdn_ciscohdlck_ops;
struct inl_cisco {
u32 myseq; /* local keepalive seq. for Cisco */
u32 mineseen; /* returned keepalive seq. from remote */
u32 yourseq; /* remote keepalive seq. for Cisco */
int keepalive_period; /* keepalive period */
int last_slarp_in; /* jiffie of last recvd keepalive pkt */
char line_state; /* state of line */
char debserint; /* debugging flags */
struct timer_list timer;
};
#endif #endif
...@@ -69,6 +69,29 @@ int register_isdn_netif(int encap, struct isdn_netif_ops *ops); ...@@ -69,6 +69,29 @@ int register_isdn_netif(int encap, struct isdn_netif_ops *ops);
/* ====================================================================== */ /* ====================================================================== */
/* Feature- and status-flags for a net-interface */
#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */
#define ISDN_NET_CALLBACK 0x04 /* activate callback */
#define ISDN_NET_CBHUP 0x08 /* hangup before callback */
#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */
#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
/* Phone-list-element */
struct isdn_net_phone {
struct list_head list;
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) */ /* per network interface data (dev->priv) */
struct isdn_net_local_s { struct isdn_net_local_s {
...@@ -128,18 +151,8 @@ struct isdn_net_local_s { ...@@ -128,18 +151,8 @@ struct isdn_net_local_s {
struct slcompress *slcomp; struct slcompress *slcomp;
#endif #endif
#endif #endif
void *inl_priv; /* interface types can put their
/* use an own struct for that in later versions */ private data here */
ulong cisco_myseq; /* Local keepalive seq. for Cisco */
ulong cisco_mineseen; /* returned keepalive seq. from remote */
ulong cisco_yourseq; /* Remote keepalive seq. for Cisco */
int cisco_keepalive_period; /* keepalive period */
ulong cisco_last_slarp_in; /* jiffie of last keepalive packet we received */
char cisco_line_state; /* state of line according to keepalive packets */
char cisco_debserint; /* debugging flag of cisco hdlc with slarp */
struct timer_list cisco_timer;
struct isdn_netif_ops *ops; struct isdn_netif_ops *ops;
struct net_device dev; /* interface to upper levels */ struct net_device dev; /* interface to upper levels */
......
...@@ -253,33 +253,6 @@ typedef struct { ...@@ -253,33 +253,6 @@ typedef struct {
/* GLOBAL_FLAGS */ /* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1 #define ISDN_GLOBAL_STOPPED 1
/*=================== Start of ip-over-ISDN stuff =========================*/
/* Feature- and status-flags for a net-interface */
#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */
#define ISDN_NET_CALLBACK 0x04 /* activate callback */
#define ISDN_NET_CBHUP 0x08 /* hangup before callback */
#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */
#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
/* Phone-list-element */
struct isdn_net_phone {
struct list_head list;
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)
*/
/*===================== End of ip-over-ISDN stuff ===========================*/
/*======================= Start of ISDN-tty stuff ===========================*/ /*======================= Start of ISDN-tty stuff ===========================*/
#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ #define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
......
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