* RE: sctp: num_ostreams and max_instreams negotiation @ 2020-08-14 13:36 ` David Laight 0 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-14 13:36 UTC (permalink / raw) To: linux-sctp@vger.kernel.org, Neil Horman; +Cc: netdev@vger.kernel.org PiA+IEF0IHNvbWUgcG9pbnQgdGhlIG5lZ290aWF0aW9uIG9mIHRoZSBudW1iZXIgb2YgU0NUUCBz dHJlYW1zDQo+ID4gc2VlbXMgdG8gaGF2ZSBnb3QgYnJva2VuLg0KPiA+IEkndmUgZGVmaW5pdGVs eSB0ZXN0ZWQgaXQgaW4gdGhlIHBhc3QgKHByb2JhYmx5IDEwIHllYXJzIGFnbyEpDQo+ID4gYnV0 IG9uIGEgNS44LjAga2VybmVsIGdldHNvY2tvcHQoU0NUUF9JTkZPKSBzZWVtcyB0byBiZQ0KPiA+ IHJldHVybmluZyB0aGUgJ251bV9vc3RyZWFtcycgc2V0IGJ5IHNldHNvY2tvcHQoU0NUUF9JTklU KQ0KPiA+IHJhdGhlciB0aGFuIHRoZSBzbWFsbGVyIG9mIHRoYXQgdmFsdWUgYW5kIHRoYXQgY29u ZmlndXJlZA0KPiA+IGF0IHRoZSBvdGhlciBlbmQgb2YgdGhlIGNvbm5lY3Rpb24uDQo+ID4NCj4g PiBJJ2xsIGRvIGEgYml0IG9mIGRpZ2dpbmcuDQo+IA0KPiBJIGNhbid0IGZpbmQgdGhlIGNvZGUg dGhhdCBwcm9jZXNzZXMgdGhlIGluaXRfYWNrLg0KPiBCdXQgd2hlbiBzY3RwX3Byb2Nzc19pbnQo KSBzYXZlcyB0aGUgc21hbGxlciB2YWx1ZQ0KPiBpbiBhc29jLT5jLnNpbmludF9tYXhfb3N0cmVh bXMuDQo+IA0KPiBCdXQgYWZlODk5OTYyZWUwNzkgKGlmIEkndmUgdHlwZWQgaXQgcmlnaHQpIGNo YW5nZWQNCj4gdGhlIHZhbHVlcyBTQ1RQX0lORk8gcmVwb3J0ZWQuDQo+IEFwcGFyYW50bHkgYWRk aW5nICdzY3RwIHJlY29uZmlnJyBoYWQgY2hhbmdlZCB0aGluZ3MuDQo+IA0KPiBTbyBJIHN1c3Bl Y3QgdGhpcyBoYXMgYWxsIGJlZW4gYnJva2VuIGZvciBvdmVyIDMgeWVhcnMuDQoNCkl0IGxvb2tz IGxpa2UgdGhlIGNoYW5nZXMgdGhhdCBicm9rZSBpdCB3ZW50IGludG8gNC4xMS4NCkkndmUganVz dCBjaGVja2VkIGEgMy44IGtlcm5lbCBhbmQgdGhhdCBuZWdvdGlhdGVzIHRoZQ0KdmFsdWVzIGRv d24gaW4gYm90aCBkaXJlY3Rpb25zLg0KDQpJIGRvbid0IGhhdmUgYW55IGtlcm5lbHMgbHVya2lu ZyBiZXR3ZWVuIDMuOCBhbmQgNC4xNS4NCihZZXMsIEkgY291bGQgYnVpbGQgb25lLCBidXQgaXQg ZG9lc24ndCByZWFsbHkgaGVscC4pDQoNCglEYXZpZA0KDQotDQpSZWdpc3RlcmVkIEFkZHJlc3Mg TGFrZXNpZGUsIEJyYW1sZXkgUm9hZCwgTW91bnQgRmFybSwgTWlsdG9uIEtleW5lcywgTUsxIDFQ VCwgVUsNClJlZ2lzdHJhdGlvbiBObzogMTM5NzM4NiAoV2FsZXMpDQo ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation @ 2020-08-14 13:36 ` David Laight 0 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-14 13:36 UTC (permalink / raw) To: linux-sctp@vger.kernel.org, Neil Horman; +Cc: netdev@vger.kernel.org > > At some point the negotiation of the number of SCTP streams > > seems to have got broken. > > I've definitely tested it in the past (probably 10 years ago!) > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > rather than the smaller of that value and that configured > > at the other end of the connection. > > > > I'll do a bit of digging. > > I can't find the code that processes the init_ack. > But when sctp_procss_int() saves the smaller value > in asoc->c.sinint_max_ostreams. > > But afe899962ee079 (if I've typed it right) changed > the values SCTP_INFO reported. > Apparantly adding 'sctp reconfig' had changed things. > > So I suspect this has all been broken for over 3 years. It looks like the changes that broke it went into 4.11. I've just checked a 3.8 kernel and that negotiates the values down in both directions. I don't have any kernels lurking between 3.8 and 4.15. (Yes, I could build one, but it doesn't really help.) David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation 2020-08-14 13:36 ` David Laight @ 2020-08-14 16:18 ` David Laight -1 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-14 16:18 UTC (permalink / raw) To: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', Andrew Morton Cc: 'netdev@vger.kernel.org' PiA+ID4gQXQgc29tZSBwb2ludCB0aGUgbmVnb3RpYXRpb24gb2YgdGhlIG51bWJlciBvZiBTQ1RQ IHN0cmVhbXMNCj4gPiA+IHNlZW1zIHRvIGhhdmUgZ290IGJyb2tlbi4NCj4gPiA+IEkndmUgZGVm aW5pdGVseSB0ZXN0ZWQgaXQgaW4gdGhlIHBhc3QgKHByb2JhYmx5IDEwIHllYXJzIGFnbyEpDQo+ ID4gPiBidXQgb24gYSA1LjguMCBrZXJuZWwgZ2V0c29ja29wdChTQ1RQX0lORk8pIHNlZW1zIHRv IGJlDQo+ID4gPiByZXR1cm5pbmcgdGhlICdudW1fb3N0cmVhbXMnIHNldCBieSBzZXRzb2Nrb3B0 KFNDVFBfSU5JVCkNCj4gPiA+IHJhdGhlciB0aGFuIHRoZSBzbWFsbGVyIG9mIHRoYXQgdmFsdWUg YW5kIHRoYXQgY29uZmlndXJlZA0KPiA+ID4gYXQgdGhlIG90aGVyIGVuZCBvZiB0aGUgY29ubmVj dGlvbi4NCj4gPiA+DQo+ID4gPiBJJ2xsIGRvIGEgYml0IG9mIGRpZ2dpbmcuDQo+ID4NCj4gPiBJ IGNhbid0IGZpbmQgdGhlIGNvZGUgdGhhdCBwcm9jZXNzZXMgdGhlIGluaXRfYWNrLg0KPiA+IEJ1 dCB3aGVuIHNjdHBfcHJvY3NzX2ludCgpIHNhdmVzIHRoZSBzbWFsbGVyIHZhbHVlDQo+ID4gaW4g YXNvYy0+Yy5zaW5pbnRfbWF4X29zdHJlYW1zLg0KPiA+DQo+ID4gQnV0IGFmZTg5OTk2MmVlMDc5 IChpZiBJJ3ZlIHR5cGVkIGl0IHJpZ2h0KSBjaGFuZ2VkDQo+ID4gdGhlIHZhbHVlcyBTQ1RQX0lO Rk8gcmVwb3J0ZWQuDQo+ID4gQXBwYXJhbnRseSBhZGRpbmcgJ3NjdHAgcmVjb25maWcnIGhhZCBj aGFuZ2VkIHRoaW5ncy4NCj4gPg0KPiA+IFNvIEkgc3VzcGVjdCB0aGlzIGhhcyBhbGwgYmVlbiBi cm9rZW4gZm9yIG92ZXIgMyB5ZWFycy4NCj4gDQo+IEl0IGxvb2tzIGxpa2UgdGhlIGNoYW5nZXMg dGhhdCBicm9rZSBpdCB3ZW50IGludG8gNC4xMS4NCj4gSSd2ZSBqdXN0IGNoZWNrZWQgYSAzLjgg a2VybmVsIGFuZCB0aGF0IG5lZ290aWF0ZXMgdGhlDQo+IHZhbHVlcyBkb3duIGluIGJvdGggZGly ZWN0aW9ucy4NCj4gDQo+IEkgZG9uJ3QgaGF2ZSBhbnkga2VybmVscyBsdXJraW5nIGJldHdlZW4g My44IGFuZCA0LjE1Lg0KPiAoWWVzLCBJIGNvdWxkIGJ1aWxkIG9uZSwgYnV0IGl0IGRvZXNuJ3Qg cmVhbGx5IGhlbHAuKQ0KDQpPaywgYnVnIGxvY2F0ZWQgLSBwcmV0dHkgb2J2aW91cyByZWFsbHku DQpuZXQvc2N0cC9zdHJlYW0uIGhhcyB0aGUgZm9sbG93aW5nIGNvZGU6DQoNCnN0YXRpYyBpbnQg c2N0cF9zdHJlYW1fYWxsb2Nfb3V0KHN0cnVjdCBzY3RwX3N0cmVhbSAqc3RyZWFtLCBfX3UxNiBv dXRjbnQsDQoJCQkJIGdmcF90IGdmcCkNCnsNCglpbnQgcmV0Ow0KDQoJaWYgKG91dGNudCA8PSBz dHJlYW0tPm91dGNudCkNCgkJcmV0dXJuIDA7DQoNCglyZXQgPSBnZW5yYWRpeF9wcmVhbGxvYygm c3RyZWFtLT5vdXQsIG91dGNudCwgZ2ZwKTsNCglpZiAocmV0KQ0KCQlyZXR1cm4gcmV0Ow0KDQoJ c3RyZWFtLT5vdXRjbnQgPSBvdXRjbnQ7DQoJcmV0dXJuIDA7DQp9DQoNCnNjdHBfc3RyZWFtX2Fs bG9jX2luKCkgaXMgdGhlIHNhbWUuDQoNClRoaXMgaXMgY2FsbGVkIHRvIHJlZHVjZSB0aGUgbnVt YmVyIG9mIHN0cmVhbXMuDQpCdXQgaW4gdGhhdCBjYXNlIGl0IGRvZXMgbm90aGluZyBhdCBhbGwu DQoNCldoaWNoIG1lYW5zIHRoYXQgdGhlICdjb252ZXJ0IHRvIGdlbnJhZGl4JyBjaGFuZ2UgYnJv a2UgaXQuDQpUYWcgMjA3NWU1MGNhZjVlYS4NCg0KSSBkb24ndCBrbm93IHdoYXQgJ2dlbnJhZGl4 JyBhcnJheXMgb3IgdGhlIGVhcmxpZXIgJ2ZsZXhfYXJyYXknDQphY3R1YWxseSBsb29rIGxpa2Uu DQpCdXQgaWYgJ2dlbnJhZGl4JyBpcyBzb21lIGtpbmQgb2YgcmFkaXgtdHJlZSBpdCBpcyBwcm9i YWJseSB0aGUNCndyb25nIGJlYXN0IGZvciBTQ1RQIHN0cmVhbXMuDQpMb3RzIG9mIGNvZGUgbG9v cHMgdGhyb3VnaCBhbGwgb2YgdGhlbS4NCg0KVGhpcyBkb2VzIG1lYW4gdGhhdCBpdCBoYXMgb25s eSBiZWVuIGJyb2tlbiBzaW5jZSB0aGUgNS4xDQptZXJnZSB3aW5kb3cuDQoNCldoaWxlIGp1c3Qg YXNzaWduaW5nIHRvIHN0cmVhbS0+b3V0Y250IHdoZW4gdGhlIHZhbHVlDQppcyByZWR1Y2VkIHdp bGwgZml4IHRoZSBuZWdvdGlhdGlvbiwgSSd2ZSBubyBpZGVhDQp3aGF0IHNpZGUtZWZmZWN0cyB0 aGF0IGhhcy4NCg0KCURhdmlkDQoNCg0KCURhdmlkDQoNCi0NClJlZ2lzdGVyZWQgQWRkcmVzcyBM YWtlc2lkZSwgQnJhbWxleSBSb2FkLCBNb3VudCBGYXJtLCBNaWx0b24gS2V5bmVzLCBNSzEgMVBU LCBVSw0KUmVnaXN0cmF0aW9uIE5vOiAxMzk3Mzg2IChXYWxlcykNCg= ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation @ 2020-08-14 16:18 ` David Laight 0 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-14 16:18 UTC (permalink / raw) To: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', Andrew Morton Cc: 'netdev@vger.kernel.org' > > > At some point the negotiation of the number of SCTP streams > > > seems to have got broken. > > > I've definitely tested it in the past (probably 10 years ago!) > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > rather than the smaller of that value and that configured > > > at the other end of the connection. > > > > > > I'll do a bit of digging. > > > > I can't find the code that processes the init_ack. > > But when sctp_procss_int() saves the smaller value > > in asoc->c.sinint_max_ostreams. > > > > But afe899962ee079 (if I've typed it right) changed > > the values SCTP_INFO reported. > > Apparantly adding 'sctp reconfig' had changed things. > > > > So I suspect this has all been broken for over 3 years. > > It looks like the changes that broke it went into 4.11. > I've just checked a 3.8 kernel and that negotiates the > values down in both directions. > > I don't have any kernels lurking between 3.8 and 4.15. > (Yes, I could build one, but it doesn't really help.) Ok, bug located - pretty obvious really. net/sctp/stream. has the following code: static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, gfp_t gfp) { int ret; if (outcnt <= stream->outcnt) return 0; ret = genradix_prealloc(&stream->out, outcnt, gfp); if (ret) return ret; stream->outcnt = outcnt; return 0; } sctp_stream_alloc_in() is the same. This is called to reduce the number of streams. But in that case it does nothing at all. Which means that the 'convert to genradix' change broke it. Tag 2075e50caf5ea. I don't know what 'genradix' arrays or the earlier 'flex_array' actually look like. But if 'genradix' is some kind of radix-tree it is probably the wrong beast for SCTP streams. Lots of code loops through all of them. This does mean that it has only been broken since the 5.1 merge window. While just assigning to stream->outcnt when the value is reduced will fix the negotiation, I've no idea what side-effects that has. David David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation 2020-08-14 16:18 ` David Laight @ 2020-08-15 14:49 ` David Laight -1 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-15 14:49 UTC (permalink / raw) To: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton' Cc: 'netdev@vger.kernel.org' RnJvbTogRGF2aWQgTGFpZ2h0DQo+IFNlbnQ6IDE0IEF1Z3VzdCAyMDIwIDE3OjE4DQo+IA0KPiA+ ID4gPiBBdCBzb21lIHBvaW50IHRoZSBuZWdvdGlhdGlvbiBvZiB0aGUgbnVtYmVyIG9mIFNDVFAg c3RyZWFtcw0KPiA+ID4gPiBzZWVtcyB0byBoYXZlIGdvdCBicm9rZW4uDQo+ID4gPiA+IEkndmUg ZGVmaW5pdGVseSB0ZXN0ZWQgaXQgaW4gdGhlIHBhc3QgKHByb2JhYmx5IDEwIHllYXJzIGFnbyEp DQo+ID4gPiA+IGJ1dCBvbiBhIDUuOC4wIGtlcm5lbCBnZXRzb2Nrb3B0KFNDVFBfSU5GTykgc2Vl bXMgdG8gYmUNCj4gPiA+ID4gcmV0dXJuaW5nIHRoZSAnbnVtX29zdHJlYW1zJyBzZXQgYnkgc2V0 c29ja29wdChTQ1RQX0lOSVQpDQo+ID4gPiA+IHJhdGhlciB0aGFuIHRoZSBzbWFsbGVyIG9mIHRo YXQgdmFsdWUgYW5kIHRoYXQgY29uZmlndXJlZA0KPiA+ID4gPiBhdCB0aGUgb3RoZXIgZW5kIG9m IHRoZSBjb25uZWN0aW9uLg0KPiA+ID4gPg0KPiA+ID4gPiBJJ2xsIGRvIGEgYml0IG9mIGRpZ2dp bmcuDQo+ID4gPg0KPiA+ID4gSSBjYW4ndCBmaW5kIHRoZSBjb2RlIHRoYXQgcHJvY2Vzc2VzIHRo ZSBpbml0X2Fjay4NCj4gPiA+IEJ1dCB3aGVuIHNjdHBfcHJvY3NzX2ludCgpIHNhdmVzIHRoZSBz bWFsbGVyIHZhbHVlDQo+ID4gPiBpbiBhc29jLT5jLnNpbmludF9tYXhfb3N0cmVhbXMuDQo+ID4g Pg0KPiA+ID4gQnV0IGFmZTg5OTk2MmVlMDc5IChpZiBJJ3ZlIHR5cGVkIGl0IHJpZ2h0KSBjaGFu Z2VkDQo+ID4gPiB0aGUgdmFsdWVzIFNDVFBfSU5GTyByZXBvcnRlZC4NCj4gPiA+IEFwcGFyYW50 bHkgYWRkaW5nICdzY3RwIHJlY29uZmlnJyBoYWQgY2hhbmdlZCB0aGluZ3MuDQo+ID4gPg0KPiA+ ID4gU28gSSBzdXNwZWN0IHRoaXMgaGFzIGFsbCBiZWVuIGJyb2tlbiBmb3Igb3ZlciAzIHllYXJz Lg0KPiA+DQo+ID4gSXQgbG9va3MgbGlrZSB0aGUgY2hhbmdlcyB0aGF0IGJyb2tlIGl0IHdlbnQg aW50byA0LjExLg0KPiA+IEkndmUganVzdCBjaGVja2VkIGEgMy44IGtlcm5lbCBhbmQgdGhhdCBu ZWdvdGlhdGVzIHRoZQ0KPiA+IHZhbHVlcyBkb3duIGluIGJvdGggZGlyZWN0aW9ucy4NCj4gPg0K PiA+IEkgZG9uJ3QgaGF2ZSBhbnkga2VybmVscyBsdXJraW5nIGJldHdlZW4gMy44IGFuZCA0LjE1 Lg0KPiA+IChZZXMsIEkgY291bGQgYnVpbGQgb25lLCBidXQgaXQgZG9lc24ndCByZWFsbHkgaGVs cC4pDQo+IA0KPiBPaywgYnVnIGxvY2F0ZWQgLSBwcmV0dHkgb2J2aW91cyByZWFsbHkuDQo+IG5l dC9zY3RwL3N0cmVhbS4gaGFzIHRoZSBmb2xsb3dpbmcgY29kZToNCj4gDQo+IHN0YXRpYyBpbnQg c2N0cF9zdHJlYW1fYWxsb2Nfb3V0KHN0cnVjdCBzY3RwX3N0cmVhbSAqc3RyZWFtLCBfX3UxNiBv dXRjbnQsDQo+IAkJCQkgZ2ZwX3QgZ2ZwKQ0KPiB7DQo+IAlpbnQgcmV0Ow0KPiANCj4gCWlmIChv dXRjbnQgPD0gc3RyZWFtLT5vdXRjbnQpDQo+IAkJcmV0dXJuIDA7DQoNCkRlbGV0aW5nIHRoaXMg Y2hlY2sgaXMgc3VmZmljaWVudCB0byBmaXggdGhlIGNvZGUuDQpBbG9uZyB3aXRoIHRoZSBlcXVp dmFsZW50IGNoZWNrIGluIHNjdHBfc3RyZWFtLWFsbG9jX2luKCkuDQoNCg0KPiBUaGlzIGRvZXMg bWVhbiB0aGF0IGl0IGhhcyBvbmx5IGJlZW4gYnJva2VuIHNpbmNlIHRoZSA1LjENCj4gbWVyZ2Ug d2luZG93Lg0KDQpBbmQgaXMgYSBnb29kIGNhbmRpZGF0ZSBmb3IgdGhlIGJhY2stcG9ydHMuDQoN Cj4gCXJldCA9IGdlbnJhZGl4X3ByZWFsbG9jKCZzdHJlYW0tPm91dCwgb3V0Y250LCBnZnApOw0K PiAJaWYgKHJldCkNCj4gCQlyZXR1cm4gcmV0Ow0KPiANCj4gCXN0cmVhbS0+b3V0Y250ID0gb3V0 Y250Ow0KPiAJcmV0dXJuIDA7DQo+IH0NCj4gDQo+IHNjdHBfc3RyZWFtX2FsbG9jX2luKCkgaXMg dGhlIHNhbWUuDQo+IA0KPiBUaGlzIGlzIGNhbGxlZCB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBz dHJlYW1zLg0KPiBCdXQgaW4gdGhhdCBjYXNlIGl0IGRvZXMgbm90aGluZyBhdCBhbGwuDQo+IA0K PiBXaGljaCBtZWFucyB0aGF0IHRoZSAnY29udmVydCB0byBnZW5yYWRpeCcgY2hhbmdlIGJyb2tl IGl0Lg0KPiBUYWcgMjA3NWU1MGNhZjVlYS4NCj4gDQo+IEkgZG9uJ3Qga25vdyB3aGF0ICdnZW5y YWRpeCcgYXJyYXlzIG9yIHRoZSBlYXJsaWVyICdmbGV4X2FycmF5Jw0KPiBhY3R1YWxseSBsb29r IGxpa2UuDQo+IEJ1dCBpZiAnZ2VucmFkaXgnIGlzIHNvbWUga2luZCBvZiByYWRpeC10cmVlIGl0 IGlzIHByb2JhYmx5IHRoZQ0KPiB3cm9uZyBiZWFzdCBmb3IgU0NUUCBzdHJlYW1zLg0KPiBMb3Rz IG9mIGNvZGUgbG9vcHMgdGhyb3VnaCBhbGwgb2YgdGhlbS4NCg0KWWVwLCBJJ20gcHJldHR5IHN1 cmUgYSBrdm1hbGxvYygpIHdvdWxkIGJlIGJlc3QuDQoNCj4gV2hpbGUganVzdCBhc3NpZ25pbmcg dG8gc3RyZWFtLT5vdXRjbnQgd2hlbiB0aGUgdmFsdWUNCj4gaXMgcmVkdWNlZCB3aWxsIGZpeCB0 aGUgbmVnb3RpYXRpb24sIEkndmUgbm8gaWRlYQ0KPiB3aGF0IHNpZGUtZWZmZWN0cyB0aGF0IGhh cy4NCg0KSSd2ZSBkb25lIHNvbWUgY2hlY2tzLg0KVGhlIGFycmF5cyBhcmUgYWxsb2NhdGVkIHdo ZW4gYW4gSU5JVCBpcyBzZW50IGFuZCBhbHNvIGJlZm9yZQ0KYSByZWNlaXZlZCBJTklUIGlzIHBy b2Nlc3NlZC4NClNvIGlmIG9uZSBzaWRlIChlZyB0aGUgcmVzcG9uZGVyKSBhbGxvY2F0ZXMgYSB2 ZXJ5IGJpZyB2YWx1ZQ0KdGhlbiB0aGUgYXNzb2NpYXRlZCBtZW1vcnkgaXMgbmV2ZXIgZnJlZWQg d2hlbiB0aGUgdmFsdWUNCmlzIG5lZ290aWF0ZWQgZG93bi4NClRoZXJlIGlzIGEgY29tbWVudCB0 byB0aGUgZWZmZWN0IHRoYXQgdGhpcyBpcyBkZXNpcmFibGUuDQoNCklmIG15IHF1aWNrIGNhbGN1 bGF0aW9ucyBhcmUgY29ycmVjdCB0aGVuIGVhY2ggJ2luJyBpcyAyMCBieXRlcw0KYW5kIGVhY2gg J291dCcgMjQgKHdpdGggYSBsb3Qgb2YgcGFkIGJ5dGVzKS4NClNvIHRoZSBtYXggc2l6ZXMgYXJl IDMyMiBhbmQgMzg2IDRrIHBhZ2VzLg0KDQpJIGhhdmVuJ3QgbG9va2VkIGF0IGhvdyBtYW55IG9m IHRoZSAnb3V0JyBzdHJlYW1zIGdldHMgdGhlDQpleHRyYSwgc2VwYXJhdGVseSBhbGxvY2F0ZWQs IHN0cnVjdHVyZS4NCkkgc3VzcGVjdCB0aGUgbWVtb3J5IGZvb3RwcmludCBmb3IgYSBzaW5nbGUg U0NUUCBjb25uZWN0aW9uDQppcyBwb3RlbnRpYWxseSBodWdlLg0KDQoJRGF2aWQNCg0KLQ0KUmVn aXN0ZXJlZCBBZGRyZXNzIExha2VzaWRlLCBCcmFtbGV5IFJvYWQsIE1vdW50IEZhcm0sIE1pbHRv biBLZXluZXMsIE1LMSAxUFQsIFVLDQpSZWdpc3RyYXRpb24gTm86IDEzOTczODYgKFdhbGVzKQ0K ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation @ 2020-08-15 14:49 ` David Laight 0 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-15 14:49 UTC (permalink / raw) To: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton' Cc: 'netdev@vger.kernel.org' From: David Laight > Sent: 14 August 2020 17:18 > > > > > At some point the negotiation of the number of SCTP streams > > > > seems to have got broken. > > > > I've definitely tested it in the past (probably 10 years ago!) > > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > > rather than the smaller of that value and that configured > > > > at the other end of the connection. > > > > > > > > I'll do a bit of digging. > > > > > > I can't find the code that processes the init_ack. > > > But when sctp_procss_int() saves the smaller value > > > in asoc->c.sinint_max_ostreams. > > > > > > But afe899962ee079 (if I've typed it right) changed > > > the values SCTP_INFO reported. > > > Apparantly adding 'sctp reconfig' had changed things. > > > > > > So I suspect this has all been broken for over 3 years. > > > > It looks like the changes that broke it went into 4.11. > > I've just checked a 3.8 kernel and that negotiates the > > values down in both directions. > > > > I don't have any kernels lurking between 3.8 and 4.15. > > (Yes, I could build one, but it doesn't really help.) > > Ok, bug located - pretty obvious really. > net/sctp/stream. has the following code: > > static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, > gfp_t gfp) > { > int ret; > > if (outcnt <= stream->outcnt) > return 0; Deleting this check is sufficient to fix the code. Along with the equivalent check in sctp_stream-alloc_in(). > This does mean that it has only been broken since the 5.1 > merge window. And is a good candidate for the back-ports. > ret = genradix_prealloc(&stream->out, outcnt, gfp); > if (ret) > return ret; > > stream->outcnt = outcnt; > return 0; > } > > sctp_stream_alloc_in() is the same. > > This is called to reduce the number of streams. > But in that case it does nothing at all. > > Which means that the 'convert to genradix' change broke it. > Tag 2075e50caf5ea. > > I don't know what 'genradix' arrays or the earlier 'flex_array' > actually look like. > But if 'genradix' is some kind of radix-tree it is probably the > wrong beast for SCTP streams. > Lots of code loops through all of them. Yep, I'm pretty sure a kvmalloc() would be best. > While just assigning to stream->outcnt when the value > is reduced will fix the negotiation, I've no idea > what side-effects that has. I've done some checks. The arrays are allocated when an INIT is sent and also before a received INIT is processed. So if one side (eg the responder) allocates a very big value then the associated memory is never freed when the value is negotiated down. There is a comment to the effect that this is desirable. If my quick calculations are correct then each 'in' is 20 bytes and each 'out' 24 (with a lot of pad bytes). So the max sizes are 322 and 386 4k pages. I haven't looked at how many of the 'out' streams gets the extra, separately allocated, structure. I suspect the memory footprint for a single SCTP connection is potentially huge. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: sctp: num_ostreams and max_instreams negotiation 2020-08-15 14:49 ` David Laight @ 2020-08-17 14:22 ` Marcelo Ricardo Leitner -1 siblings, 0 replies; 11+ messages in thread From: Marcelo Ricardo Leitner @ 2020-08-17 14:22 UTC (permalink / raw) To: David Laight Cc: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton', 'netdev@vger.kernel.org' On Sat, Aug 15, 2020 at 02:49:31PM +0000, David Laight wrote: > From: David Laight > > Sent: 14 August 2020 17:18 > > > > > > > At some point the negotiation of the number of SCTP streams > > > > > seems to have got broken. > > > > > I've definitely tested it in the past (probably 10 years ago!) > > > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > > > rather than the smaller of that value and that configured > > > > > at the other end of the connection. > > > > > > > > > > I'll do a bit of digging. > > > > > > > > I can't find the code that processes the init_ack. > > > > But when sctp_procss_int() saves the smaller value > > > > in asoc->c.sinint_max_ostreams. > > > > > > > > But afe899962ee079 (if I've typed it right) changed > > > > the values SCTP_INFO reported. > > > > Apparantly adding 'sctp reconfig' had changed things. > > > > > > > > So I suspect this has all been broken for over 3 years. > > > > > > It looks like the changes that broke it went into 4.11. > > > I've just checked a 3.8 kernel and that negotiates the > > > values down in both directions. > > > > > > I don't have any kernels lurking between 3.8 and 4.15. > > > (Yes, I could build one, but it doesn't really help.) > > > > Ok, bug located - pretty obvious really. > > net/sctp/stream. has the following code: > > > > static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, > > gfp_t gfp) > > { > > int ret; > > > > if (outcnt <= stream->outcnt) > > return 0; > > Deleting this check is sufficient to fix the code. > Along with the equivalent check in sctp_stream-alloc_in(). 2075e50caf5e has: - if (outcnt > stream->outcnt) - fa_zero(out, stream->outcnt, (outcnt - stream->outcnt)); + if (outcnt <= stream->outcnt) + return 0; - stream->out = out; + ret = genradix_prealloc(&stream->out, outcnt, gfp); + if (ret) + return ret; + stream->outcnt = outcnt; return 0; The flip on the if() return missed that stream->outcnt needs to be updated later on even if it is reducing the size. The proper fix here is to move back to the original if() condition, and put genradix_prealloc() inside it again, as was fa_zero() before. The if() is not strictly needed, because genradix_prealloc() will handle it nicely, but it's a nice-to-have optimization anyway. Do you want to send a patch? > > > > This does mean that it has only been broken since the 5.1 > > merge window. > > And is a good candidate for the back-ports. Yep. > > > ret = genradix_prealloc(&stream->out, outcnt, gfp); > > if (ret) > > return ret; > > > > stream->outcnt = outcnt; > > return 0; > > } > > > > sctp_stream_alloc_in() is the same. > > > > This is called to reduce the number of streams. > > But in that case it does nothing at all. > > > > Which means that the 'convert to genradix' change broke it. > > Tag 2075e50caf5ea. > > > > I don't know what 'genradix' arrays or the earlier 'flex_array' > > actually look like. > > But if 'genradix' is some kind of radix-tree it is probably the > > wrong beast for SCTP streams. > > Lots of code loops through all of them. > > Yep, I'm pretty sure a kvmalloc() would be best. kvmalloc() doesn't help here because these functions can be called form bh. Note how sctp_process_strreset_addstrm_in(), for example, needs to use GFP_ATOMIC in there, in which kvmalloc() can't fallback to vmalloc. > > > While just assigning to stream->outcnt when the value > > is reduced will fix the negotiation, I've no idea > > what side-effects that has. > > I've done some checks. > The arrays are allocated when an INIT is sent and also before > a received INIT is processed. > So if one side (eg the responder) allocates a very big value > then the associated memory is never freed when the value > is negotiated down. > There is a comment to the effect that this is desirable. > > If my quick calculations are correct then each 'in' is 20 bytes > and each 'out' 24 (with a lot of pad bytes). > So the max sizes are 322 and 386 4k pages. > > I haven't looked at how many of the 'out' streams gets the > extra, separately allocated, structure. > I suspect the memory footprint for a single SCTP connection > is potentially huge. This shouldn't be an issue. The default amount of out streams is low (10, SCTP_DEFAULT_OUTSTREAMS) and the 'in' ones are only allocated when we have such info already. That's why sctp_connect_new_asoc() and sctp_association_init() will pass incnt=0 for sctp_stream_init(). Marcelo ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: sctp: num_ostreams and max_instreams negotiation @ 2020-08-17 14:22 ` Marcelo Ricardo Leitner 0 siblings, 0 replies; 11+ messages in thread From: Marcelo Ricardo Leitner @ 2020-08-17 14:22 UTC (permalink / raw) To: David Laight Cc: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton', 'netdev@vger.kernel.org' On Sat, Aug 15, 2020 at 02:49:31PM +0000, David Laight wrote: > From: David Laight > > Sent: 14 August 2020 17:18 > > > > > > > At some point the negotiation of the number of SCTP streams > > > > > seems to have got broken. > > > > > I've definitely tested it in the past (probably 10 years ago!) > > > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > > > rather than the smaller of that value and that configured > > > > > at the other end of the connection. > > > > > > > > > > I'll do a bit of digging. > > > > > > > > I can't find the code that processes the init_ack. > > > > But when sctp_procss_int() saves the smaller value > > > > in asoc->c.sinint_max_ostreams. > > > > > > > > But afe899962ee079 (if I've typed it right) changed > > > > the values SCTP_INFO reported. > > > > Apparantly adding 'sctp reconfig' had changed things. > > > > > > > > So I suspect this has all been broken for over 3 years. > > > > > > It looks like the changes that broke it went into 4.11. > > > I've just checked a 3.8 kernel and that negotiates the > > > values down in both directions. > > > > > > I don't have any kernels lurking between 3.8 and 4.15. > > > (Yes, I could build one, but it doesn't really help.) > > > > Ok, bug located - pretty obvious really. > > net/sctp/stream. has the following code: > > > > static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, > > gfp_t gfp) > > { > > int ret; > > > > if (outcnt <= stream->outcnt) > > return 0; > > Deleting this check is sufficient to fix the code. > Along with the equivalent check in sctp_stream-alloc_in(). 2075e50caf5e has: - if (outcnt > stream->outcnt) - fa_zero(out, stream->outcnt, (outcnt - stream->outcnt)); + if (outcnt <= stream->outcnt) + return 0; - stream->out = out; + ret = genradix_prealloc(&stream->out, outcnt, gfp); + if (ret) + return ret; + stream->outcnt = outcnt; return 0; The flip on the if() return missed that stream->outcnt needs to be updated later on even if it is reducing the size. The proper fix here is to move back to the original if() condition, and put genradix_prealloc() inside it again, as was fa_zero() before. The if() is not strictly needed, because genradix_prealloc() will handle it nicely, but it's a nice-to-have optimization anyway. Do you want to send a patch? > > > > This does mean that it has only been broken since the 5.1 > > merge window. > > And is a good candidate for the back-ports. Yep. > > > ret = genradix_prealloc(&stream->out, outcnt, gfp); > > if (ret) > > return ret; > > > > stream->outcnt = outcnt; > > return 0; > > } > > > > sctp_stream_alloc_in() is the same. > > > > This is called to reduce the number of streams. > > But in that case it does nothing at all. > > > > Which means that the 'convert to genradix' change broke it. > > Tag 2075e50caf5ea. > > > > I don't know what 'genradix' arrays or the earlier 'flex_array' > > actually look like. > > But if 'genradix' is some kind of radix-tree it is probably the > > wrong beast for SCTP streams. > > Lots of code loops through all of them. > > Yep, I'm pretty sure a kvmalloc() would be best. kvmalloc() doesn't help here because these functions can be called form bh. Note how sctp_process_strreset_addstrm_in(), for example, needs to use GFP_ATOMIC in there, in which kvmalloc() can't fallback to vmalloc. > > > While just assigning to stream->outcnt when the value > > is reduced will fix the negotiation, I've no idea > > what side-effects that has. > > I've done some checks. > The arrays are allocated when an INIT is sent and also before > a received INIT is processed. > So if one side (eg the responder) allocates a very big value > then the associated memory is never freed when the value > is negotiated down. > There is a comment to the effect that this is desirable. > > If my quick calculations are correct then each 'in' is 20 bytes > and each 'out' 24 (with a lot of pad bytes). > So the max sizes are 322 and 386 4k pages. > > I haven't looked at how many of the 'out' streams gets the > extra, separately allocated, structure. > I suspect the memory footprint for a single SCTP connection > is potentially huge. This shouldn't be an issue. The default amount of out streams is low (10, SCTP_DEFAULT_OUTSTREAMS) and the 'in' ones are only allocated when we have such info already. That's why sctp_connect_new_asoc() and sctp_association_init() will pass incnt=0 for sctp_stream_init(). Marcelo ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: sctp: num_ostreams and max_instreams negotiation 2020-08-17 14:22 ` Marcelo Ricardo Leitner @ 2020-08-17 14:35 ` Marcelo Ricardo Leitner -1 siblings, 0 replies; 11+ messages in thread From: Marcelo Ricardo Leitner @ 2020-08-17 14:35 UTC (permalink / raw) To: David Laight Cc: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton', 'netdev@vger.kernel.org' On Mon, Aug 17, 2020 at 11:22:23AM -0300, Marcelo Ricardo Leitner wrote: > On Sat, Aug 15, 2020 at 02:49:31PM +0000, David Laight wrote: > > From: David Laight > > > Sent: 14 August 2020 17:18 > > > > > > > > > At some point the negotiation of the number of SCTP streams > > > > > > seems to have got broken. > > > > > > I've definitely tested it in the past (probably 10 years ago!) > > > > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > > > > rather than the smaller of that value and that configured > > > > > > at the other end of the connection. > > > > > > > > > > > > I'll do a bit of digging. > > > > > > > > > > I can't find the code that processes the init_ack. > > > > > But when sctp_procss_int() saves the smaller value > > > > > in asoc->c.sinint_max_ostreams. > > > > > > > > > > But afe899962ee079 (if I've typed it right) changed > > > > > the values SCTP_INFO reported. > > > > > Apparantly adding 'sctp reconfig' had changed things. > > > > > > > > > > So I suspect this has all been broken for over 3 years. > > > > > > > > It looks like the changes that broke it went into 4.11. > > > > I've just checked a 3.8 kernel and that negotiates the > > > > values down in both directions. > > > > > > > > I don't have any kernels lurking between 3.8 and 4.15. > > > > (Yes, I could build one, but it doesn't really help.) > > > > > > Ok, bug located - pretty obvious really. > > > net/sctp/stream. has the following code: > > > > > > static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, > > > gfp_t gfp) > > > { > > > int ret; > > > > > > if (outcnt <= stream->outcnt) > > > return 0; > > > > Deleting this check is sufficient to fix the code. > > Along with the equivalent check in sctp_stream-alloc_in(). > > 2075e50caf5e has: > > - if (outcnt > stream->outcnt) > - fa_zero(out, stream->outcnt, (outcnt - stream->outcnt)); > + if (outcnt <= stream->outcnt) > + return 0; > > - stream->out = out; > + ret = genradix_prealloc(&stream->out, outcnt, gfp); > + if (ret) > + return ret; > > + stream->outcnt = outcnt; > return 0; > > The flip on the if() return missed that stream->outcnt needs to be > updated later on even if it is reducing the size. > > The proper fix here is to move back to the original if() condition, > and put genradix_prealloc() inside it again, as was fa_zero() before. > The if() is not strictly needed, because genradix_prealloc() will > handle it nicely, but it's a nice-to-have optimization anyway. > > Do you want to send a patch? Note the thread 'Subject: RE: v5.3.12 SCTP Stream Negotiation Problem' though. Marcelo ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: sctp: num_ostreams and max_instreams negotiation @ 2020-08-17 14:35 ` Marcelo Ricardo Leitner 0 siblings, 0 replies; 11+ messages in thread From: Marcelo Ricardo Leitner @ 2020-08-17 14:35 UTC (permalink / raw) To: David Laight Cc: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton', 'netdev@vger.kernel.org' On Mon, Aug 17, 2020 at 11:22:23AM -0300, Marcelo Ricardo Leitner wrote: > On Sat, Aug 15, 2020 at 02:49:31PM +0000, David Laight wrote: > > From: David Laight > > > Sent: 14 August 2020 17:18 > > > > > > > > > At some point the negotiation of the number of SCTP streams > > > > > > seems to have got broken. > > > > > > I've definitely tested it in the past (probably 10 years ago!) > > > > > > but on a 5.8.0 kernel getsockopt(SCTP_INFO) seems to be > > > > > > returning the 'num_ostreams' set by setsockopt(SCTP_INIT) > > > > > > rather than the smaller of that value and that configured > > > > > > at the other end of the connection. > > > > > > > > > > > > I'll do a bit of digging. > > > > > > > > > > I can't find the code that processes the init_ack. > > > > > But when sctp_procss_int() saves the smaller value > > > > > in asoc->c.sinint_max_ostreams. > > > > > > > > > > But afe899962ee079 (if I've typed it right) changed > > > > > the values SCTP_INFO reported. > > > > > Apparantly adding 'sctp reconfig' had changed things. > > > > > > > > > > So I suspect this has all been broken for over 3 years. > > > > > > > > It looks like the changes that broke it went into 4.11. > > > > I've just checked a 3.8 kernel and that negotiates the > > > > values down in both directions. > > > > > > > > I don't have any kernels lurking between 3.8 and 4.15. > > > > (Yes, I could build one, but it doesn't really help.) > > > > > > Ok, bug located - pretty obvious really. > > > net/sctp/stream. has the following code: > > > > > > static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt, > > > gfp_t gfp) > > > { > > > int ret; > > > > > > if (outcnt <= stream->outcnt) > > > return 0; > > > > Deleting this check is sufficient to fix the code. > > Along with the equivalent check in sctp_stream-alloc_in(). > > 2075e50caf5e has: > > - if (outcnt > stream->outcnt) > - fa_zero(out, stream->outcnt, (outcnt - stream->outcnt)); > + if (outcnt <= stream->outcnt) > + return 0; > > - stream->out = out; > + ret = genradix_prealloc(&stream->out, outcnt, gfp); > + if (ret) > + return ret; > > + stream->outcnt = outcnt; > return 0; > > The flip on the if() return missed that stream->outcnt needs to be > updated later on even if it is reducing the size. > > The proper fix here is to move back to the original if() condition, > and put genradix_prealloc() inside it again, as was fa_zero() before. > The if() is not strictly needed, because genradix_prealloc() will > handle it nicely, but it's a nice-to-have optimization anyway. > > Do you want to send a patch? Note the thread 'Subject: RE: v5.3.12 SCTP Stream Negotiation Problem' though. Marcelo ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: sctp: num_ostreams and max_instreams negotiation 2020-08-17 14:35 ` Marcelo Ricardo Leitner (?) @ 2020-08-18 8:08 ` David Laight -1 siblings, 0 replies; 11+ messages in thread From: David Laight @ 2020-08-18 8:08 UTC (permalink / raw) To: 'Marcelo Ricardo Leitner' Cc: 'linux-sctp@vger.kernel.org', 'Neil Horman', 'kent.overstreet@gmail.com', 'Andrew Morton', 'netdev@vger.kernel.org' From: Marcelo Ricardo Leitner > Sent: 17 August 2020 15:36 .. > > The proper fix here is to move back to the original if() condition, > > and put genradix_prealloc() inside it again, as was fa_zero() before. > > The if() is not strictly needed, because genradix_prealloc() will > > handle it nicely, but it's a nice-to-have optimization anyway. > > > > Do you want to send a patch? I can, but my systems aren't really setup for doing it. Especially while working from home. Just deleting the conditionals works for normal connections. I don't know what happens if the number of streams is negotiated up and down (and up again?) while the connection is active. > Note the thread 'Subject: RE: v5.3.12 SCTP Stream Negotiation Problem' > though. The patch you suggested contained a typo: - if (incnt <= stream->incnt) - return 0; + if (incnt > stream->incnt) + goto out; So the 'in' array was never allocated. The code will still allocate a 'big' array which I think used to get shrunk when the value from the peer was processed. I suspect the array need not get allocated until after that is done (ISTR in process_init). I also suspect that the genradix lookup is more expensive than the sctp code expects. I wonder if a straight forward kvmalloc() wouldn't be better. You'd actually need kvrealloc(). All the sctp connections we use have a max of 17 streams. But if someone allocates 64k and then uses them sparsely it still allocates about 700 pages for the genradix arrays. Also, since the 'gfp' flags are being passed in, I suspect the allocate happens in atomic context somewhere. I bet allocating 700 pages is very likely to fail! Lazy allocation would only require single pages be allocated, but would need extra error paths. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2020-08-18 8:08 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-08-14 13:36 sctp: num_ostreams and max_instreams negotiation David Laight 2020-08-14 13:36 ` David Laight 2020-08-14 16:18 ` David Laight 2020-08-14 16:18 ` David Laight 2020-08-15 14:49 ` David Laight 2020-08-15 14:49 ` David Laight 2020-08-17 14:22 ` Marcelo Ricardo Leitner 2020-08-17 14:22 ` Marcelo Ricardo Leitner 2020-08-17 14:35 ` Marcelo Ricardo Leitner 2020-08-17 14:35 ` Marcelo Ricardo Leitner 2020-08-18 8:08 ` David Laight
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.